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]
withnums[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
.
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
(whereq
is the quotient andr
is the remainder) - After
r
operations:S - r = q * k + r - r = q * k
- Now
(S - r) % k = 0
, making it divisible byk
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 requirek + r
operations - Since we want the minimum operations, we choose
r
overk + 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:
-
Calculate the sum of all array elements: We iterate through the array
nums
and compute the total sum using Python's built-insum()
function. -
Apply the modulo operation: We take the sum and compute
sum % k
to find the remainder when the sum is divided byk
. -
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)
wheren
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 between0
andk-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 EvaluatorExample 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
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
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!