Problem overview
The function max_sum receives a vector of integers, nums, and a positive integer k. It looks at every contiguous subarray of length exactly k, finds the one with the largest sum, and returns its start and end indices as a vector of two i32 values.
In the example, nums = [5, 6, 1, 2, 6, 6, 4, 3] and k = 3. The window from index 4 to index 6 holds 6, 6 and 4, which add up to 16, more than any other window of three. The function returns [4, 6].
Approach: add up every window
A window of length k is fixed by where it starts. The first window starts at index 0, and the last one must still have room for k elements, so it starts at n - k. That makes n - k + 1 windows. For the example, n = 8 and k = 3 give six windows, starting at 0 through 5.
The six windows of the example have these sums, in order: 12, 9, 9, 14, 16 and 13. The largest, 16, belongs to the window starting at index 4, so the stored answer ends as [4, 6]. The answer vector changes only when the running best improves, which here happens at windows 0, 3 and 4.
The brute force adds up the k elements of each window from scratch and remembers the best sum together with the window's indices. Each of the n - k + 1 windows costs k additions, which is O(n * k) time. A follow-up lesson on this problem slides the window and reuses most of the previous sum, which brings the time down to O(n).
When two windows tie, the earlier one wins here. The comparison is a strict "greater than", so a later window with an equal sum doesn't replace the stored answer. For [1, 3, 2, 2, 3, 1] with k = 2, the windows starting at 1 and 3 both sum to 5, and the answer is [1, 2], the first of them.
Step by step
- Create
bestasi32::MIN. It tracks the largest window sum so far. Window sums can be negative, so the start must lie below every possible sum, and the smallesti32does. - Create
answer, a mutable vector holding the first window's bounds,0andk - 1. The starting code has already turnedkinto ausize, so it is cast back withas i32for the result. - Loop over the window starts with
ifrom 0 ton - kinclusive, written with..=. - Sum the window. The slice
nums[i..i + k]has exactlykelements, anditer().sum()adds them. The variable is annotated asi32so thatsum()knows what to produce. - Compare and record. If this sum beats
best, store it and replaceanswerwith the window's first and last index. - Return
answeras the last expression.
The solution in Rust
impl Solution {
fn max_sum(nums: Vec<i32>, k: i32) -> Vec<i32> {
let k = k as usize;
let n = nums.len();
let mut best = i32::MIN;
let mut answer = vec![0i32, k as i32 - 1];
for i in 0..=(n - k) {
let sum: i32 = nums[i..i + k].iter().sum();
if sum > best {
best = sum;
answer = vec![i as i32, (i + k - 1) as i32];
}
}
answer
}
}
The Rust details worth a closer look:
- Shadowing.
let k = k as usize;declares a newkthat hides thei32parameter. From then onkis ausize, the type that indexes and slice bounds need. - The cast and the minus. In
k as i32 - 1, the cast binds tighter than the subtraction, so it means(k as i32) - 1. The second index in the loop,(i + k - 1) as i32, does the arithmetic inusizefirst and casts the result. - Slices.
nums[i..i + k]borrows part of the vector without copying it. The upper bound is excluded, which is why a slice of lengthkstarting atiends ati + kand its last element has indexi + k - 1. - Inclusive range.
0..=(n - k)includesn - k. Without the=, the last window would be skipped. usizesubtraction. Ifkis larger thann,n - kcan't go below zero. In a debug build it panics. In an optimized build it wraps to a huge number, and the first slice then panics with an out-of-range message. Either way, aklarger than the vector isn't handled, and the lesson assumes it doesn't happen.- Tail expression.
answerhas no semicolon, so the function returns it.
Complexity
Time: O(n * k). There are n - k + 1 windows, and summing each one reads k elements. When k is close to n / 2 the cost is about n²/4.
Space: O(1). The slice is a borrowed view, so no window is copied. Only best and the two-element answer are stored.
Edge cases and common mistakes
kequals the length. Withk = 8on the example,n - kis 0, there is one window, and the answer is[0, 7].k = 1. Every element is its own window. The example returns[1, 1], the first 6, because ties keep the earliest window.- Negative values. For
[-5, -2, -7, -1]withk = 2, the window sums are -7, -9 and -8, so the answer is[0, 1]. Startingbestat 0 would never accept any of them. - Off-by-one in the slice.
nums[i..i + k - 1]sums onlyk - 1elements. The slice ends one past the last element it contains. - Returning the sum. The function returns the two indices, not the sum.
Testing
[5, 6, 1, 2, 6, 6, 4, 3]withk = 3gives[4, 6].- The same vector with
k = 8gives[0, 7]. - The same vector with
k = 1gives[1, 1]. [1, 3, 2, 2, 3, 1]withk = 2gives[1, 2].[-5, -2, -7, -1]withk = 2gives[0, 1].
