Problem overview
The method maxSum receives an array of integers nums and a positive integer k. Among all contiguous windows of exactly k elements, it must find the one with the largest sum and return its first and last index as [start, end].
For nums = [5, 6, 1, 2, 6, 6, 4, 3] and k = 3, the window at indices 4 to 6 holds 6, 6, 4 and sums to 16, the largest of all windows. The method returns [4, 6].
Approach: slide the window instead of re-adding it
The brute-force way adds up all k elements of every window, which costs O(n * k). But two neighbouring windows share k - 1 elements. Moving the window one step to the right changes only two things: the element at its left end leaves, and a new element enters at its right end.
So the new sum is the old sum, minus the element that left, plus the element that arrived:
sum = sum - nums[i - 1] + nums[i + k - 1]
That takes constant time, no matter how big k is. Compute the first window's sum once with a plain loop, then slide across the array and update the sum in O(1) per step. Each element enters the window once and leaves it once, so the total is O(n).
On the example, the first window [5, 6, 1] sums to 12. Sliding gives these sums for the starts 1 to 5:
| start i | left out | added | sum |
|---|---|---|---|
| 1 | 5 | 2 | 9 |
| 2 | 6 | 6 | 9 |
| 3 | 1 | 6 | 14 |
| 4 | 2 | 4 | 16 |
| 5 | 6 | 3 | 13 |
The best sum, 16, comes at start 4, so the answer is [4, 6].
Step by step
- Create
answerholding the first window's bounds,[0, k - 1]. If no later window beats the first, this is already correct. Starting with an empty array would return nothing whenever the first window is the best one. - Create
sumat 0. It will track the sum of the current window. - Add the first
kelements with a loop over the indices0..<k. Nowsumis the first window's total. - Create
maxSumfromsum. The first window is the best seen so far, and it is a real window, so there is no need for a sentinel likeInt.min. - Set up a
whileloop withistarting at 1. The loop runs whilei <= nums.count - k, which is the last valid start, andi += 1goes at the bottom of its body. - Slide the window by subtracting
nums[i - 1], the element that just left, and addingnums[i + k - 1], the one that just entered. - Compare with the best. If
sumis strictly greater thanmaxSum, save it and setanswerto[i, i + k - 1]. The strict comparison keeps the earliest window when sums tie. - Return
answerafter the loop.
The solution in Swift
class Solution {
func maxSum(_ nums: [Int], _ k: Int) -> [Int] {
var answer = [0, k - 1]
var sum = 0
for i in 0..<k {
sum += nums[i]
}
var maxSum = sum
var i = 1
while i <= nums.count - k {
sum = sum - nums[i - 1] + nums[i + k - 1]
if sum > maxSum {
maxSum = sum
answer = [i, i + k - 1]
}
i += 1
}
return answer
}
}
The Swift details worth knowing:
- Two different
ivariables. Theiin theforloop exists only inside that loop. After it ends,var i = 1declares a new variable with the same name, which Swift allows because the first one is out of scope. whileand the manual counter. The loop variable must change by hand, withi += 1. Swift has no++operator. If the increment is skipped, the loop never ends.- Type inference.
[0, k - 1]is inferred as[Int], which matches the return type, andansweris avarbecause it gets replaced later. - A method and a variable called
maxSum. Inside the method, the namemaxSummeans the local variable. That is legal. - Invalid
k. Ifkis larger thannums.count, the first loop reads past the end of the array and the program stops with a run-time error. Swift checks array indices. The lesson's tests keepkwithin the array.
Complexity
Time: O(n). The first loop does k additions and the while loop runs n - k times with a constant amount of work each, so the total is about n steps.
Space: O(1). The method keeps a few integers and the two-element result.
Edge cases and common mistakes
kequals the array length. The condition1 <= nums.count - kis false at the start, so the loop body never runs and the answer stays[0, k - 1].kis 1. Each window is a single element.[-3, -1, -2]withk = 1gives[1, 1].- Ties. In
[2, 2, 2, 2]withk = 2every sum is 4, and the result is the first window,[0, 1]. - Negative numbers. Starting
maxSumfrom the first window, not from 0, handles inputs where every window sum is negative. - Wrong index leaving or entering. The element that leaves is
nums[i - 1], and the element that enters isnums[i + k - 1]. Usingnums[i + k]is off by one and reads past the end on the last window. - Loop bound. Using
i < nums.count - kinstead of<=skips the last window. For[1, 2, 3, 10]withk = 2, the best window[3, 10]would never be checked. - Putting
i += 1before the slide. The two statements usei, so the increment belongs at the bottom of the body.
Testing
nums = [5, 6, 1, 2, 6, 6, 4, 3],k = 3gives[4, 6].nums = [1, 2, 3],k = 3gives[0, 2].nums = [2, 2, 2, 2],k = 2gives[0, 1].nums = [4, -9, 4],k = 1gives[0, 0].
