Skip to content

← Ground Rules: Values, Types, Control Flow step 21 of 24

Medium Primitives

Find the largest window sum with slices

Fix max_window_sum so it returns the largest sum of k consecutive elements, or None when the requested window size is invalid:

pub fn max_window_sum(values: &[i32], k: usize) -> Option<i32>

A valid window has at least one element and fits entirely inside the input. Return None when k == 0 or k > values.len(). This also covers empty input. A valid window can have a zero or negative sum, so neither is a marker for a missing answer.

Values k Result
[1, 2, 3, 4] 2 Some(7)
[5] 1 Some(5)
[-5, -1, -3] 2 Some(-4)
[1, 2, 3, 4] 4 Some(10)
[1] 2 None
[1, 2] 0 None

The starter compiles and passes Clippy, but panics for k == 0. Add the boundary check before it creates the windows. You can keep the existing sum-and-maximum pipeline. Inputs keep the additions within i32 range.

Borrow a sequence through a slice

The parameter &[i32] is a shared reference to a sequence of integers. It gives the function access to the elements and their count without transferring ownership or copying the input. The caller can pass a vector, an array or part of either:

let array = [1, 2, 3, 4];
let vector = vec![1, 2, 3, 4];
assert_eq!(max_window_sum(&array, 2), Some(7));
assert_eq!(max_window_sum(&vector, 2), Some(7));
assert_eq!(max_window_sum(&array[1..3], 2), Some(5));

At this parameter, &Vec<i32> converts through deref coercion to &[i32]. An array reference &[i32; N] converts through an unsizing coercion. Both produce the slice reference the function needs, but they use different rules.

A slice reference carries length information as well as access to the data. It is commonly called a wide pointer. You do not need to depend on its byte size or layout to use the slice API. A mutable slice, &mut [i32], would also permit changing elements; this function only needs shared access.

Windows overlap

For [1, 2, 3, 4], windows(2) yields borrowed slices [1, 2], [2, 3] and [3, 4]. Their sums are 3, 5 and 7, so the answer is Some(7). The windows are contiguous and overlap; they are not disjoint chunks.

windows handles the two invalid sizes differently:

  • A size greater than the slice length produces an empty iterator.
  • A zero size panics when windows(0) is called.

An empty iterator is safe to pass to max(), which returns None. The zero case must be rejected earlier. Returning None for it is this function's contract, rather than behavior supplied by windows itself.

Read the pipeline

values.windows(k).map(|w| w.iter().sum::<i32>()).max()

map computes a sum for each window. max returns the largest sum, already wrapped in Some, or None if there were no windows. Starting a running best value at zero would incorrectly beat every window in an all-negative input.

The explicit ::<i32> states the sum's output type. Rust can sometimes infer that type from surrounding code, including this function's return type; an unconstrained use of sum() may need an annotation.

This implementation recomputes each window's sum. For a valid size it performs work proportional to (values.len() - k + 1) * k. A rolling sum is a separate optimization; it is not needed to fix the starter's boundary behavior.

The solution must compile, return the expected values and pass clippy -D warnings.