Problem overview
The function longest_subarray receives a vector of positive integers, nums, and a limit s. It must find the longest contiguous subarray whose sum is at most s and return its first and last index as a vector of two i32 values.
In the example, nums = [3, 2, 5, 2, 2, 1, 1, 3, 1, 2] and s = 11. The subarray at indices 3 to 8 is [2, 2, 1, 1, 3, 1], with sum 10. Extending it by one element on the right gives 12, which is over the limit, so the answer is [3, 8]. The statement allows O(n²) time and O(1) extra space.
Approach: every start, growing end
A subarray is fixed by its start and its end. Fix the start i and extend the end j one element at a time. The sum of nums[i..=j] then needs only one addition per step, because it is the previous sum plus nums[j]. Whenever that sum is within the limit and the subarray is longer than the best one so far, the answer is updated.
Without the running sum, adding up every subarray from scratch would take O(n³) time. Reusing the sum as the end moves right brings it down to O(n²), the budget the statement sets.
There is a tie in the example. The subarray at indices 4 to 9 also has length 6, and it sums to 2 + 1 + 1 + 3 + 1 + 2 = 10. The comparison max_len < ... is strict, so only a strictly longer subarray replaces the stored one, and the earlier [3, 8] stays.
Step by step
- Create
answerasvec![0i32, 0i32]. It will hold the start and end of the longest valid subarray found so far. If no element fits unders, the function returns[0, 0]. - Create
max_lenas0i32. Any valid subarray is longer than 0, so the first valid one replaces it. - Loop over the start
ifrom 0 ton - 1, using thenthe starting code provides. - Declare
sumas0i32inside that loop. It restarts at 0 for every new start. - Loop over the end
jfromiton - 1. - Add
nums[j]tosum. Nowsumcovers indicesitoj. - Test two conditions together: the sum is at most
s, and the lengthj - i + 1beatsmax_len. The length is ausize, so it is cast toi32for the comparison. - Record the new length in
max_len. - Record the indices in
answer, each cast withas i32. - Return
answerafter both loops, as the tail expression.
The solution in Rust
impl Solution {
fn longest_subarray(nums: Vec<i32>, s: i32) -> Vec<i32> {
let n = nums.len();
let mut answer = vec![0i32, 0i32];
let mut max_len = 0i32;
for i in 0..n {
let mut sum = 0i32;
for j in i..n {
sum += nums[j];
if sum <= s && max_len < (j - i + 1) as i32 {
max_len = (j - i + 1) as i32;
answer = vec![i as i32, j as i32];
}
}
}
answer
}
}
The Rust details worth a closer look:
- Two integer types. The indices
iandjareusize, because they come from ranges overnand index the vector. The sums, the length counter and the result arei32. Rust never converts between them silently, so the lengthj - i + 1must be cast withas i32before it meetsmax_len. - The cast placement. The parentheses in
(j - i + 1) as i32make the cast apply to the whole length. Sincej >= i, the subtraction never goes below zero. - Short-circuit
&&. Ifsum <= sis false, the length comparison isn't evaluated. vec![i as i32, j as i32]. The macro builds a new vector, and assigning it toanswerdrops the old one.- Tail expression.
answerhas no semicolon. With one, the function would return()and not compile. - Overflow. The running
sumis ani32. In an optimized build, a sum past thei32range wraps and could pass thesum <= stest by accident; a debug build panics instead.
Complexity
Time: O(n²). The outer loop runs n times and the inner loop up to n times, with constant work for each pair. That makes about n(n + 1) / 2 steps in total.
Space: O(1). A few integers and the two-element answer.
The inner loop could stop as soon as sum exceeds s. All the numbers are positive, so extending the subarray can only raise the sum. This lesson's version keeps scanning, which is correct, just wasteful. That monotonic property is also what lets a faster two-pointer method reach O(n).
Edge cases and common mistakes
- No element fits.
[4, 5]withs = 3returns[0, 0]. That is the starting value ofanswer, so the result looks like a valid one-element subarray even though nothing qualifies. - A single element qualifies.
[3, 2, 5, 2, 2, 1, 1, 3, 1, 2]withs = 1returns[5, 5], the first 1. Withs = 0nothing fits and the result is[0, 0]. - The whole vector fits. With
s = 100the example returns[0, 9]. - Ties. The strict
<keeps the earliest of several equally long subarrays. Using<=would keep the latest. - Forgetting to reset
sum. Declaring it outside the outer loop would carry totals from one start into the next. - Comparing the sum, not the length. The best subarray is the longest one, not the one with the largest sum.
Testing
[3, 2, 5, 2, 2, 1, 1, 3, 1, 2]withs = 11gives[3, 8].- The same vector with
s = 1gives[5, 5]. - The same vector with
s = 100gives[0, 9]. [4, 1]withs = 3gives[1, 1].
