class Solution:
def minOperations(self, nums1, nums2):
from collections import Counter
n1, n2 = len(nums1), len(nums2)
s1, s2 = sum(nums1), sum(nums2)
if 6 * n1 < n2 or 6 * n2 < n1:
return -1
if s1 == s2:
return 0
# Always make s1 < s2
if s1 > s2:
nums1, nums2 = nums2, nums1
s1, s2 = s2, s1
diff = s2 - s1
count = [0] * 6 # index 1..5, possible change values
for x in nums1:
count[6 - x] += 1 # increase nums1
for x in nums2:
count[x - 1] += 1 # decrease nums2
ops = 0
for change in range(5, 0, -1):
while count[change] > 0 and diff > 0:
take = min(count[change], (diff + change - 1) // change)
diff -= take * change
ops += take
count[change] -= take
return ops if diff <= 0 else -1
class Solution {
public:
int minOperations(vector<int>& nums1, vector<int>& nums2) {
int n1 = nums1.size(), n2 = nums2.size();
int s1 = accumulate(nums1.begin(), nums1.end(), 0);
int s2 = accumulate(nums2.begin(), nums2.end(), 0);
if (6 * n1 < n2 || 6 * n2 < n1) return -1;
if (s1 == s2) return 0;
if (s1 > s2) {
swap(nums1, nums2);
swap(s1, s2);
}
int diff = s2 - s1;
vector<int> count(6, 0);
for (int x : nums1) count[6 - x]++;
for (int x : nums2) count[x - 1]++;
int ops = 0;
for (int change = 5; change > 0 && diff > 0; --change) {
while (count[change] > 0 && diff > 0) {
int take = min(count[change], (diff + change - 1) / change);
diff -= take * change;
ops += take;
count[change] -= take;
}
}
return diff <= 0 ? ops : -1;
}
};
class Solution {
public int minOperations(int[] nums1, int[] nums2) {
int n1 = nums1.length, n2 = nums2.length;
int s1 = 0, s2 = 0;
for (int x : nums1) s1 += x;
for (int x : nums2) s2 += x;
if (6 * n1 < n2 || 6 * n2 < n1) return -1;
if (s1 == s2) return 0;
if (s1 > s2) {
int[] tmp = nums1; nums1 = nums2; nums2 = tmp;
int t = s1; s1 = s2; s2 = t;
}
int diff = s2 - s1;
int[] count = new int[6];
for (int x : nums1) count[6 - x]++;
for (int x : nums2) count[x - 1]++;
int ops = 0;
for (int change = 5; change > 0 && diff > 0; --change) {
while (count[change] > 0 && diff > 0) {
int take = Math.min(count[change], (diff + change - 1) / change);
diff -= take * change;
ops += take;
count[change] -= take;
}
}
return diff <= 0 ? ops : -1;
}
}
var minOperations = function(nums1, nums2) {
let n1 = nums1.length, n2 = nums2.length;
let s1 = nums1.reduce((a,b) => a+b, 0);
let s2 = nums2.reduce((a,b) => a+b, 0);
if (6 * n1 < n2 || 6 * n2 < n1) return -1;
if (s1 === s2) return 0;
if (s1 > s2) {
[nums1, nums2] = [nums2, nums1];
[s1, s2] = [s2, s1];
}
let diff = s2 - s1;
let count = Array(6).fill(0);
for (let x of nums1) count[6 - x]++;
for (let x of nums2) count[x - 1]++;
let ops = 0;
for (let change = 5; change > 0 && diff > 0; --change) {
while (count[change] > 0 && diff > 0) {
let take = Math.min(count[change], Math.floor((diff + change - 1) / change));
diff -= take * change;
ops += take;
count[change] -= take;
}
}
return diff <= 0 ? ops : -1;
};
You are given two integer arrays, nums1
and nums2
. Each element in both arrays is an integer between 1 and 6 (inclusive). In one operation, you can change any single element in either array to any value between 1 and 6.
Your goal is to make the sum of nums1
equal to the sum of nums2
using the minimum number of operations. Return the minimum number of operations needed, or -1
if it's impossible.
The first instinct is to try brute force: try all combinations of element changes in both arrays and see which sequence leads to equal sums with the least operations. However, this is not feasible for large arrays because the number of possibilities grows exponentially.
Next, we notice that each element can be changed to either 1 or 6, so the maximum change per operation is 5 (e.g., changing a 1 to a 6 or vice versa). To minimize operations, we should make the largest possible sum changes in each operation.
We also need to consider the difference between the sums of the two arrays. Our goal is to reduce this difference to zero using the fewest number of operations, always maximizing the effect of each operation.
The key insight is to treat each possible element change as a potential "gain" in closing the gap between the two sums, and use the largest available gains first.
nums1
and nums2
. If nums1
's sum is greater, swap the arrays (and their sums) so that nums1
is always the array with the smaller sum. This ensures we always "increase" nums1
and/or "decrease" nums2
.
nums1
, the largest gain is 6 - value
(changing it to 6). For each element in nums2
, the largest gain is value - 1
(changing it to 1). Count how many elements can provide each possible gain (from 1 to 5).
-1
(impossible). Otherwise, return the operation count.
6 * len(nums1) < len(nums2)
or vice versa, and return -1
in that case.
This approach uses a greedy strategy to always make the most impactful operation available, ensuring the minimum number of steps.
Example:
nums1 = [1,2,3,4,5,6]
, nums2 = [1,1,2,2,2,2]
nums1
= 21nums2
= 10nums1
is larger, swap the arrays to always work with the smaller sum first.nums1 = [1,1,2,2,2,2]
(sum 10), nums2 = [1,2,3,4,5,6]
(sum 21), difference = 11.nums1
, possible increases: [5,5,4,4,4,4]
nums2
, possible decreases: [0,1,2,3,4,5]
[5,5,4,4,4,4,5,4,3,2,1,0]
[5,5,5,4,4,4,4,4,3,2,1,0]
n
and m
, the number of possibilities is huge and impractical.
The solution leverages a greedy approach to minimize operations: always pick the change that brings the two sums closest together. By counting the number of possible "gains" for each change, and using the largest gains first, we ensure the minimum number of operations. This method is both efficient and elegant, handling all edge cases and working in linear time with respect to the input size.