Problem overview
The method RemoveMinSum receives an int[] nums and a number k. You must pick exactly k numbers, some from the beginning of the array and some from the end, so that their sum is as small as possible. The method returns that sum.
In the example, nums = [-2, 5, 2, -1, 3, -10, 9, -2] and k = 4. Picking the first number and the last three gives -2 + (-10) + 9 + (-2) = -5, which is the minimum.
Approach: minimise what you pick by maximising what you leave
The numbers you pick sit at the two ends. The numbers you don't pick form one contiguous block in the middle, and since exactly k numbers are picked, the block has exactly n - k elements. Picked sum plus block sum is always the total of the array. So:
picked sum = total - block sum
To make the picked sum as small as possible, make the block sum as large as possible. That turns the problem into one you may already know: find the maximum sum of a window of fixed length n - k. A sliding window does this in a single pass, and the answer is the total minus the best window.
In the example, the block has 4 elements. The five windows sum to 4, 9, -6, 1 and 0. The best is 9, the window [5, 2, -1, 3]. The array total is 4, and 4 - 9 = -5, which matches.
Step by step
- Reassign
k. The code setsk = nums.Length - k, so from now onkis the length of the block you keep. Parameters are ordinary local variables in C#, so assigning to one is fine, and it doesn't affect the caller. - Window sum.
rollingSumstarts at 0 and holds the sum of the current window. - Total.
totalSumstarts at 0. Adding to it during the same loop saves a separate pass. - Best window.
maxSumstarts atint.MinValue, so the first full window replaces it. Starting at 0 would be wrong if every window had a negative sum. - Loop over every index
iofnums. - Add the current number to both
totalSumandrollingSum. - Wait for a full window. The first window of
kelements is complete whenireachesk - 1. Before that, the guardi >= k - 1is false. - Record and slide. Once the window is full, update
maxSumwithMath.Max, and then subtractnums[i - k + 1], the oldest element, so that the next iteration's addition leaves a window of exactlyknumbers again. - Return
totalSum - maxSum.
Here is the loop on the example, where the window length is 4. At i = 3 the window is -2, 5, 2, -1 with sum 4, so maxSum becomes 4 and -2 is removed, leaving 6. At i = 4 the sum is 6 + 3 = 9, so maxSum becomes 9, and the removal of 5 leaves 4. The remaining windows have sums -6, 1 and 0, which never beat 9. At the end totalSum is 4, and the method returns 4 - 9 = -5.
The solution in C#
class Solution {
public int RemoveMinSum(int[] nums, int k) {
k = nums.Length - k;
int rollingSum = 0;
int totalSum = 0;
int maxSum = int.MinValue;
for (int i = 0; i < nums.Length; i++) {
totalSum += nums[i];
rollingSum += nums[i];
if (i >= k - 1) {
maxSum = Math.Max(maxSum, rollingSum);
rollingSum -= nums[i - k + 1];
}
}
return totalSum - maxSum;
}
}
C# details worth noticing
- Reusing a parameter. Overwriting
kkeeps the code short, but the name now means something different from the one the caller passed. In your own code, a new variable such aswindowSizewould be easier to read. - Subtraction after the check. The window slides inside the
if. The order matters: the sum is compared while the window is full, and only afterwards is the oldest element removed. - Overflow. The totals are
intand wrap silently beyond about two billion in magnitude. The lesson's data is small.
Complexity
Time: O(n). One pass, with constant work per element.
Space: O(1). The code uses a few int variables.
A direct approach would try each split of k into a prefix part and a suffix part and add them up, which is simple but slower. The block view finds the answer in one pass and no extra arrays.
Edge cases and common mistakes
k = 0. Nothing is picked, and the block is the whole array. The only window is the total, so the result istotal - total = 0. For the example array, the code returns 0.k = nums.Length - 1. The block has a single element, and the best one is the largest number. For the example withk = 7, the largest is 9, so the result is4 - 9 = -5.k = nums.Length. The block would be empty. This code isn't written for that case: the window length becomes 0, and the final iteration reads past the end of the array and throws anIndexOutOfRangeException. The code assumes that at least one number stays in the middle.- Wrong window size. Using the original
kas the window size would find the best block of the picked size, which is a different problem. - Starting
maxSumat 0. If the array is all negative, every window is negative and 0 would never be replaced. - Window start index. A window of
kelements ending atistarts ati - k + 1. Writingi - kremoves the wrong element.
Testing
[-2, 5, 2, -1, 3, -10, 9, -2]withk = 4returns-5.- The same array with
k = 0returns0. - The same array with
k = 7returns-5.