Equal Sum Arrays With Minimum Number of Operations
Given two arrays nums1 and nums2 of integers, where every element is between 1 and 6, you can change any element in either array to any value between 1 and 6 in one operation. Return the minimum number of operations to make the sums of nums1 and nums2 equal, or -1 if it is impossible.
This is LeetCode 1775: Equal Sum Arrays With Minimum Number of Operations, a medium problem that rewards greedy thinking. The trick is to realize that you do not need to decide which specific elements to change. You only need to count how many operations of each "gain" level are available, then use the biggest gains first.
Why this problem matters
This problem is a clean example of the greedy-with-counting pattern. Instead of trying every possible combination of changes (exponential), you observe that each operation has a measurable impact on the gap between the two sums. A change that closes the gap by 5 is always better than one that closes it by 1. So you sort the available operations by impact and consume them greedily.
The same reasoning applies to problems like assigning tasks to workers, distributing resources, or any scenario where you pick the most impactful action at each step. Once you internalize the pattern, you can recognize it instantly.
The key insight
Every element is between 1 and 6. That means the maximum you can gain from a single operation is 5 (changing a 1 to a 6, or a 6 to a 1). The minimum gain is 1 (changing a 2 to a 1, or a 5 to a 6).
For the array with the larger sum, decreasing an element toward 1 closes the gap. For the array with the smaller sum, increasing an element toward 6 closes the gap. You do not care which array a gain comes from. You only care about the magnitude of that gain.
So the algorithm is:
- Compute the gap between the two sums.
- If the gap is zero, return 0.
- Figure out which array has the larger sum. For each element in the larger-sum array, compute how much you could save by changing it to 1. For each element in the smaller-sum array, compute how much you could gain by changing it to 6.
- Count how many operations give each possible gain (1 through 5).
- Starting from gain 5 down to gain 1, use as many operations as needed to close the gap.
The feasibility check is simple: if 6 * len(nums1) is less than 1 * len(nums2), or 1 * len(nums1) is greater than 6 * len(nums2), the sums can never be made equal. In other words, the maximum possible sum of one array must be at least the minimum possible sum of the other.
The solution
def min_operations(nums1, nums2):
sum1, sum2 = sum(nums1), sum(nums2)
if sum1 == sum2:
return 0
if sum1 < sum2:
nums1, nums2 = nums2, nums1
sum1, sum2 = sum2, sum1
gap = sum1 - sum2
count = [0] * 6
for x in nums1:
count[x - 1] += 1
for x in nums2:
count[6 - x] += 1
ops = 0
for gain in range(5, 0, -1):
if gap <= 0:
break
use = min(count[gain], (gap + gain - 1) // gain)
ops += use
gap -= use * gain
return ops if gap <= 0 else -1
Here is what each section does:
- Compute the sums. If they are already equal, return 0 immediately.
- Swap so that
nums1always has the larger sum. This simplifies the logic because you only think about "closing the gap" in one direction. - For each element
xin the larger-sum array, changingxto 1 gives a gain ofx - 1. For each elementxin the smaller-sum array, changingxto 6 gives a gain of6 - x. Both of these are indexed by the samecountarray, wherecount[g]stores how many operations produce gaing. - Walk from the highest gain (5) down to 1. At each level, use the minimum of the available operations and the number needed to close the remaining gap. The ceiling division
(gap + gain - 1) // gaincomputes exactly how many operations of this gain level would be enough.
count array has only 6 slots, so building it is O(n + m) and iterating it is O(1). This is effectively a counting sort on the gains, which avoids the O(n log n) cost of a real sort.Visual walkthrough
Step 1: Count available gains from both arrays
From nums1 (larger sum), changing 6 to 1 saves 5, changing 5 to 1 saves 4, etc. From nums2 (smaller sum), changing 1 to 6 gains 5, changing 2 to 6 gains 4. Combine all gains into buckets.
Step 2: Use 1st gain-5 operation. Gap: 11 to 6.
Pick the highest-gain bucket first. One gain-5 operation reduces the gap from 11 to 6. Could be changing a 6 to 1 in nums1, or a 1 to 6 in nums2.
Step 3: Use 2nd gain-5 operation. Gap: 6 to 1.
Another gain-5 operation. Gap drops from 6 to 1. Almost there, but not yet zero.
Step 4: Use 3rd gain-5 operation. Gap closed.
One more gain-5 operation closes the remaining gap. Total: 3 operations. We did not need any gain-4 or smaller operations.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Greedy with counting | O(n + m) | O(1) |
Time is O(n + m) because you scan both arrays once to compute sums and build the gain counts. The greedy loop over gains 5 down to 1 is a fixed 5 iterations, so it contributes O(1). Space is O(1) because the count array has a constant size of 6 slots regardless of input size.
The building blocks
1. Greedy selection by impact
The core pattern here is ranking your available moves by their effect and always choosing the most impactful one first. This is the same idea behind:
- The fractional knapsack problem, where you take items with the best value-to-weight ratio first.
- Huffman coding, where you merge the two lowest-frequency nodes first.
- Any problem that asks for the minimum number of operations, where each operation has a variable cost or effect.
The pattern works whenever a locally optimal choice (biggest gain first) leads to a globally optimal result. In this problem, using a gain-5 operation before a gain-1 operation is always at least as good, because you close the gap faster and never waste smaller operations.
2. Counting sort for bounded values
When the values you need to sort live in a small, bounded range (here, gains from 1 to 5), you do not need a comparison-based sort. A counting array indexed by the value itself gives you O(n) construction and O(1) traversal. This technique shows up in problems involving dice rolls, character frequencies, digit counts, and any domain with a fixed alphabet.
Edge cases
Before submitting, make sure your solution handles these:
- Already equal sums:
nums1 = [1,1,1],nums2 = [3]. Both sum to 3. Return 0. - Impossible to equalize:
nums1 = [6,6],nums2 = [1]. Max sum ofnums2is 6, min sum ofnums1is 2. Butnums1's minimum sum (2) can equalnums2's maximum sum (6), so this is actually possible. The truly impossible case is when one array is too long:nums1 = [6] * 1,nums2 = [1] * 7. Max ofnums1is 6, min ofnums2is 7. Return -1. - Single element arrays:
nums1 = [6],nums2 = [1]. Gap is 5, one operation (change either the 6 to 1 or the 1 to 6). Return 1. - All elements the same:
nums1 = [3,3,3,3],nums2 = [3,3,3,3]. Sums are equal. Return 0. - Gap requires exact fit: when the remaining gap is 3 and you have one gain-3 operation, that is exactly enough. The ceiling division handles this correctly.
From understanding to recall
You have seen the greedy approach and it clicks. Count the gains, use the biggest first, done. But in an interview, the small details trip people up: which direction do you subtract, how do you index the count array, what is the ceiling division formula?
These details are easy to forget under pressure. Spaced repetition forces you to reconstruct the solution from scratch at increasing intervals. After a few rounds, building the count array and writing the greedy loop becomes automatic. You see "minimize operations to equalize" and the pattern flows out without hesitation.
This greedy-with-counting pattern is one of roughly 60 reusable building blocks that cover hundreds of LeetCode problems. Learning them individually and drilling them with spaced repetition is far more effective than grinding random problems.
Related posts
- Gas Station - Another greedy problem where tracking a running value replaces brute-force simulation
- Jump Game - Greedy forward scanning to determine reachability with minimum effort
- Candy - Greedy two-pass approach to minimize total cost under neighbor constraints
CodeBricks breaks this equal-sum-arrays problem into its greedy-selection and counting-sort building blocks, then drills them independently with spaced repetition. You type each piece from scratch until the pattern is automatic. When a greedy optimization question shows up in your interview, you do not think about it. You just write it.