Problem overview
The method maxSum receives an Array[Int] called nums and a positive integer k. It looks at every continuous subarray of length exactly k, finds the one with the largest sum, and returns its first and last indices as a two-element array.
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, which beats every other window. The method returns [4, 6].
Approach: add up every window
There are only n - k + 1 windows of length k in an array of n elements, one for each possible start index. The brute force is direct: for each start, add up its k elements, compare the sum with the best so far, and remember the indices if it is better.
Each window costs k additions, and there are about n windows, so the total is O(n * k). That is fine for small inputs. The sliding-window lesson on the same problem removes the repeated work by reusing the sum of the previous window.
On the example, the window sums are 12, 9, 9, 14, 16 and 13, for starts 0 through 5. The best is 16 at start 4, so the answer is [4, 6].
Three details of the specification decide how the code is written. The window has exactly k elements, so a shorter run at the end of the array never counts. The result holds indices and not the sum, so the method has to remember where the best window started. And when two windows have the same sum, the earlier one is the answer.
Step by step
- Create
maxSumas avarstarting atInt.MinValue, the smallest possibleInt. Any real window sum is at least that large, so the first window always replaces it, even when all the numbers are negative. - Create
answeras avarholding an emptyArray[Int]. It will be replaced by the bounds of the best window. - Loop over the window starts with
ifrom 0 tonums.length - k. The last window of lengthkstarts atnums.length - k, andtoincludes that value, unlikeuntil. - Declare
sumas avarequal to 0 inside the loop. It starts from zero for every window, so each window adds up its own elements. - Loop
idxfromiuntili + k. These are thekpositions of the window. Becauseuntilexcludes its upper bound, the loop visits exactlykindices. - Add
nums(idx)tosum. - Compare after the inner loop. If
sum > maxSum, setmaxSumtosumandanswertoArray(i, i + k - 1). The comparison is strict, so when two windows tie, the earlier one stays. - Return
answerafter the loops.
The solution in Scala
class Solution {
def maxSum(nums: Array[Int], k: Int): Array[Int] = {
var maxSum = Int.MinValue
var answer = Array[Int]()
for (i <- 0 to nums.length - k) {
var sum = 0
for (idx <- i until i + k) {
sum += nums(idx)
}
if (sum > maxSum) {
maxSum = sum
answer = Array(i, i + k - 1)
}
}
return answer
}
}
The Scala details worth knowing:
toversusuntil. Both build a range.0 to 5is 0, 1, 2, 3, 4, 5, while0 until 5stops at 4. The outer loop usestobecause the last window start is a valid start. The inner loop usesuntilbecausei + kis one past the window.Array[Int]()andArray(i, i + k - 1). The first builds an empty array and the second builds a two-element array whose type,Array[Int], is inferred. Becauseansweris avar, it can be pointed at a new array whenever a better window is found.- A variable named like its method. The local
var maxSumhas the same name as the methodmaxSum. Inside the body the name refers to the variable. That is legal in Scala, but a different name would be easier to read. - Indexing with parentheses.
nums(idx)reads an element. Square brackets are for type parameters. - Return value. The method returns an
Array[Int]of two numbers, the first and the last index of the window, not the sum.
Complexity
Time: O(n * k). There are n - k + 1 windows and each one adds k numbers. When k is close to n, the number of windows is small, so the product is largest around k = n / 2, where it is about n^2 / 4.
Space: O(1). The answer array always has two elements, and the other variables are single integers.
Edge cases and common mistakes
- Window the size of the array. For
[4, 2]withk = 2there is one window, starting at 0, and the result is[0, 1]. The range0 to 0still runs once, which is why the outer loop usesto. - All numbers negative. For
[-3, -1, -2]withk = 1the result is[1, 1]. StartingmaxSumat 0 would never accept any window and would return an empty array. - Ties. For
[1, 1, 1]withk = 2, both windows sum to 2, and the strict>keeps the first, giving[0, 1]. k = 1. Each window is one element, and the start and the end of the window are the same index:[7]gives[0, 0].- The end index. It is
i + k - 1, noti + k. A window of 3 starting at 4 ends at 6. klarger than the array. Thennums.length - kis negative and the range is empty, so the method returns an empty array. The lesson's inputs keepkwithin the array's length.
Testing
[5, 6, 1, 2, 6, 6, 4, 3]withk = 3gives[4, 6].[1, 1, 1]withk = 2gives[0, 1].[-3, -1, -2]withk = 1gives[1, 1].[4, 2]withk = 2gives[0, 1].[7]withk = 1gives[0, 0].
