Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1775. Equal Sum Arrays With Minimum Number of Operations - Leetcode Solution

Code Implementation

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;
};
      

Problem Description

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.

  • You may choose any element in either array at each operation.
  • Each element can be changed multiple times, but each operation can only change one element.
  • There is always at most one valid solution for each input.
  • Array lengths can be different.

Thought Process

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.

Solution Approach

  • Step 1: Compute Sums and Ensure Order
    Calculate the sums of 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.
  • Step 2: Calculate the Difference
    Find the difference between the two sums. Our goal is to bridge this gap using the fewest operations.
  • Step 3: Count Potential Gains
    For each element in 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).
  • Step 4: Greedily Apply Largest Gains
    Start from the largest possible gain (5), and apply as many of these as needed (or as available), then move to the next largest gain, and so on. For each, subtract the gain from the difference and increment the operation count.
  • Step 5: Check for Impossibility
    If after using all possible gains the difference is still greater than zero, return -1 (impossible). Otherwise, return the operation count.
  • Step 6: Edge Case
    If the arrays are too imbalanced in length (e.g., one is much longer than the other), it may be impossible to match sums even after all changes. Check if 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 Walkthrough

Example:
nums1 = [1,2,3,4,5,6], nums2 = [1,1,2,2,2,2]

  • Sum of nums1 = 21
  • Sum of nums2 = 10
  • The difference is 11. Since nums1 is larger, swap the arrays to always work with the smaller sum first.
  • Now, nums1 = [1,1,2,2,2,2] (sum 10), nums2 = [1,2,3,4,5,6] (sum 21), difference = 11.
  • For nums1, possible increases: [5,5,4,4,4,4]
  • For nums2, possible decreases: [0,1,2,3,4,5]
  • Collect all possible gains: [5,5,4,4,4,4,5,4,3,2,1,0]
  • Sort gains descending: [5,5,5,4,4,4,4,4,3,2,1,0]
  • Apply gain 5: difference = 6, operations = 1
  • Apply gain 5: difference = 1, operations = 2
  • Apply gain 5: difference = -4 (done), operations = 3
  • So, answer is 3 operations.

Time and Space Complexity

  • Brute-Force Approach:
    Would be exponential in time, as it tries all possible combinations of changes. For arrays of length n and m, the number of possibilities is huge and impractical.
  • Optimized (Greedy) Approach:
    Time Complexity: O(n + m), where n and m are the lengths of the two arrays. We make a single pass over each array to compute counts, and another pass over possible gain values (constant: 5).
    Space Complexity: O(1), since we use a small fixed-size array (of size 6) for counting, regardless of input size.

Summary

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.