Facebook Pixel

3512. Minimum Operations to Make Array Sum Divisible by K

Problem Description

You are given an integer array nums and an integer k. You can perform operations on the array where each operation consists of:

  • Selecting any index i in the array
  • Decreasing the value at that index by 1 (replacing nums[i] with nums[i] - 1)

You can perform this operation any number of times on any elements of the array.

Your goal is to find the minimum number of operations needed to make the sum of all array elements divisible by k.

For example, if the array sum is 10 and k = 3, you would need to perform 1 operation to reduce the sum to 9 (which is divisible by 3).

The key insight is that you can only decrease values (never increase them), so you need to reduce the array sum until it becomes divisible by k. The minimum number of operations required is simply the remainder when the current sum is divided by k, which can be calculated as sum(nums) % k.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

Let's think about what happens when we perform operations. Each operation decreases one element by 1, which means each operation decreases the total sum of the array by exactly 1.

If the current sum of the array is S, and we want to make it divisible by k, we need to find the smallest non-negative integer x such that (S - x) is divisible by k.

When is a number divisible by k? When it leaves a remainder of 0 when divided by k. Currently, our sum S has some remainder when divided by k. Let's call this remainder r, so S % k = r.

To make the sum divisible by k, we need to reduce it by exactly r. Why? Because:

  • If S = q * k + r (where q is the quotient and r is the remainder)
  • After r operations: S - r = q * k + r - r = q * k
  • Now (S - r) % k = 0, making it divisible by k

We can't do better than r operations because:

  • We can only decrease the sum (operations only subtract 1)
  • The next smaller number divisible by k would be (q - 1) * k, which would require k + r operations
  • Since we want the minimum operations, we choose r over k + r

Therefore, the minimum number of operations is simply sum(nums) % k.

Learn more about Math patterns.

Solution Approach

The solution is remarkably straightforward once we understand the mathematical relationship between operations and the sum modulo k.

Implementation Steps:

  1. Calculate the sum of all array elements: We iterate through the array nums and compute the total sum using Python's built-in sum() function.

  2. Apply the modulo operation: We take the sum and compute sum % k to find the remainder when the sum is divided by k.

  3. Return the result: This remainder directly gives us the minimum number of operations needed.

The Algorithm:

class Solution:
    def minOperations(self, nums: List[int], k: int) -> int:
        return sum(nums) % k

The beauty of this solution lies in its simplicity:

  • Time Complexity: O(n) where n is the length of the array, as we need to traverse all elements once to calculate the sum.
  • Space Complexity: O(1) as we only use a constant amount of extra space to store the sum.

Why this works:

  • The sum of the array is computed as S = nums[0] + nums[1] + ... + nums[n-1]
  • When we compute S % k, we get a value between 0 and k-1
  • This value represents exactly how many times we need to decrease the sum by 1 to make it divisible by k
  • Since each operation decreases the sum by exactly 1, the remainder equals the minimum number of operations

No complex data structures or algorithms are needed—just basic arithmetic and the modulo operation provide the optimal solution.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a concrete example to see how this solution works.

Example: nums = [7, 4, 8], k = 5

Step 1: Calculate the sum of the array

  • Sum = 7 + 4 + 8 = 19

Step 2: Find the remainder when dividing by k

  • 19 ÷ 5 = 3 remainder 4
  • So, 19 % 5 = 4

Step 3: Understand what this means

  • Our current sum is 19
  • The nearest number divisible by 5 (going down) is 15
  • We need to reduce 19 to 15, which requires 19 - 15 = 4 operations

Step 4: Verify our answer

  • After 4 operations (we could decrease any elements), the sum becomes 15
  • 15 ÷ 5 = 3 with remainder 0 ✓
  • 15 is divisible by 5!

Where could we apply these 4 operations? We have flexibility here. Some possibilities:

  • Decrease 7 by 4 → [3, 4, 8], sum = 15
  • Decrease 8 by 4 → [7, 4, 4], sum = 15
  • Decrease 7 by 2 and 8 by 2 → [5, 4, 6], sum = 15
  • Decrease each element once, then 4 by 1 again → [6, 2, 7], sum = 15

All paths lead to the same minimum number of operations: 4

This demonstrates why sum(nums) % k gives us the exact minimum—we just need to eliminate the remainder to reach divisibility!

Solution Implementation

1class Solution:
2    def minOperations(self, nums: List[int], k: int) -> int:
3        """
4        Calculate the minimum number of operations based on the sum of array elements modulo k.
5      
6        Args:
7            nums: List of integers
8            k: Integer divisor
9          
10        Returns:
11            The remainder when the sum of all elements is divided by k
12        """
13        # Calculate the total sum of all elements in the array
14        total_sum = sum(nums)
15      
16        # Return the remainder of the sum divided by k
17        # This represents the minimum operations needed
18        return total_sum % k
19
1class Solution {
2    /**
3     * Calculates the minimum number of operations needed based on the sum modulo k.
4     * This appears to find the remainder when the total sum is divided by k,
5     * which could represent the minimum adjustments needed to make the sum divisible by k.
6     * 
7     * @param nums the input array of integers
8     * @param k the divisor value
9     * @return the remainder of the sum of all elements divided by k
10     */
11    public int minOperations(int[] nums, int k) {
12        // Calculate the sum of all elements in the array using streams
13        int totalSum = Arrays.stream(nums).sum();
14      
15        // Return the remainder when the sum is divided by k
16        // This represents the minimum value needed to make the sum divisible by k
17        return totalSum % k;
18    }
19}
20
1class Solution {
2public:
3    /**
4     * Calculate the minimum number of operations needed
5     * @param nums - Input array of integers
6     * @param k - The divisor value
7     * @return Minimum operations required (remainder when sum is divided by k)
8     */
9    int minOperations(vector<int>& nums, int k) {
10        // Calculate the sum of all elements in the array
11        // Using std::reduce with initial value 0
12        int totalSum = reduce(nums.begin(), nums.end(), 0);
13      
14        // Return the remainder when sum is divided by k
15        // This represents the minimum operations needed
16        return totalSum % k;
17    }
18};
19
1/**
2 * Calculates the minimum number of operations needed
3 * @param nums - Array of numbers to process
4 * @param k - The divisor value
5 * @returns The remainder when the sum of all elements is divided by k
6 */
7function minOperations(nums: number[], k: number): number {
8    // Calculate the sum of all elements in the array
9    const sumOfElements = nums.reduce((accumulator, currentValue) => {
10        return accumulator + currentValue;
11    }, 0);
12  
13    // Return the remainder of the sum divided by k
14    return sumOfElements % k;
15}
16

Time and Space Complexity

The time complexity is O(n), where n is the length of the array nums. This is because the sum() function needs to iterate through all elements in the array exactly once to calculate the total sum.

The space complexity is O(1). The algorithm only uses a constant amount of extra space to store the sum result and perform the modulo operation, regardless of the input size.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Integer Overflow in Other Languages

While Python handles arbitrarily large integers gracefully, in languages like Java or C++, computing the sum of large arrays with large values can cause integer overflow.

Problem Example:

# In languages with fixed integer sizes, this could overflow:
nums = [10**9, 10**9, 10**9, ...]  # Many large values
k = 7

Solution: Use the modulo operation during summation to keep values manageable:

class Solution:
    def minOperations(self, nums: List[int], k: int) -> int:
        total_sum = 0
        for num in nums:
            total_sum = (total_sum + num) % k
        return total_sum

2. Misunderstanding the Problem Direction

A common mistake is thinking we need to make all elements divisible by k individually, rather than making the sum divisible by k.

Incorrect Interpretation:

# WRONG: Trying to make each element divisible by k
def minOperations_wrong(nums, k):
    operations = 0
    for num in nums:
        operations += num % k
    return operations

Correct Understanding: We only care about the total sum being divisible by k, not individual elements.

3. Edge Case: When Sum is Already Divisible

Some might add unnecessary checks for when the sum is already divisible by k.

Overcomplicated:

def minOperations_verbose(nums, k):
    total = sum(nums)
    if total % k == 0:
        return 0  # Unnecessary check
    return total % k

Clean Solution: The modulo operation naturally handles this case—when the sum is divisible by k, sum % k returns 0 automatically.

4. Negative Numbers Handling

If the problem allows negative numbers in the array, the modulo operation in some languages might return negative results.

Potential Issue:

# In some languages, (-5) % 3 might return -2 instead of 1
nums = [-5, 2, 1]  # sum = -2
k = 3

Solution for Consistency:

class Solution:
    def minOperations(self, nums: List[int], k: int) -> int:
        total_sum = sum(nums)
        # Ensure positive remainder
        return ((total_sum % k) + k) % k
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

You are given an array of intervals where intervals[i] = [start_i, end_i] represent the start and end of the ith interval. You need to merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input.


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More