Problem overview
The function longest_subarray receives a vector of integers, nums, and an integer k. It returns the length of the longest subarray, a run of neighbouring elements, that contains at most k different values. Repeats of the same value count only once.
For nums = [1, 2, 1, 2, 3] and k = 2 the answer is 4. The first four elements, [1, 2, 1, 2], hold only the values 1 and 2. Adding the 3 would make three distinct values, which is too many.
The lesson asks for O(n²) time and O(n) extra space.
Approach: extend from every start until the set gets too big
A subarray is determined by its first index i and its last index j. The plan is to try each i as the start, and extend j to the right one element at a time, keeping the values of the subarray in a hash set. The set ignores repeats, so its length is the number of distinct values.
The key observation is that extending a subarray can never reduce the number of distinct values. Once the set holds more than k values, every longer subarray from the same start is invalid too. The inner loop can stop there and the next start can begin.
While the set size is still at most k, the subarray from i to j is valid, and j - i + 1 is a candidate for the answer.
On [1, 2, 3, 1] with k = 2: from i = 0, the values 1 and 2 are accepted (length 2), then the 3 makes the set size 3 and the loop breaks. From i = 1, 2 and 3 are accepted (length 2), then the 1 breaks it. From i = 2, 3 and 1 give length 2. The answer is 2.
The quadratic cost comes from rebuilding the set from scratch for every start. Faster solutions avoid that by moving both ends of the window forward without starting over, but this lesson keeps the plain version so the idea is easy to see.
Step by step
- Keep the best length in
answer, declaredmutas0i32. The suffix gives it the type the function returns. - Loop over the start index
iin0..nums.len(). - Create a fresh set
distinct, amut HashSet<i32>, inside that loop so each start begins empty. - Loop over the end index
jini..nums.len(). The subarray grows by one element each time. - Insert
nums[j]intodistinct. If the value is already there, nothing changes. - Stop when there are too many values. If the set's length is greater than
k,break.len()is ausizeandkani32, and Rust compares only equal types, so the length is converted withas i32. - Update the answer. The subarray has
j - i + 1elements. Convert it withas i32and keep the larger of it andanswer. - Return
answeron its own line after the loops, with no semicolon.
The solution in Rust
use std::collections::HashSet;
impl Solution {
fn longest_subarray(nums: Vec<i32>, k: i32) -> i32 {
let mut answer = 0i32;
for i in 0..nums.len() {
let mut distinct: HashSet<i32> = HashSet::new();
for j in i..nums.len() {
distinct.insert(nums[j]);
if distinct.len() as i32 > k {
break;
}
answer = answer.max((j - i + 1) as i32);
}
}
answer
}
}
Rust details:
- Precedence of
as. Indistinct.len() as i32 > k, the cast is applied todistinct.len()first and the comparison then happens between twoi32values. A cast followed by<can confuse the parser, but a cast followed by>is fine. - No implicit conversions. Comparing a
usizewith ani32is a compile error. Every mix of integer types needs an explicitas. - Ranges.
0..nums.len()excludes its end, soiis always a valid index. For an empty vector the range is empty and the loop body doesn't run. - Copying into the set.
insert(nums[j])copies ani32, so the vector is untouched. breakexits only the inner loop, so the next start still runs.
Complexity
Time: O(n²). There are n starts, and each inner loop runs up to n steps with O(1) average work per insertion. When k is large enough that nothing breaks early, the total is about n²/2 steps.
Space: O(n). The set holds up to k + 1 values, at most n, and a new set replaces it for each start.
Edge cases and common mistakes
- Empty vector. Returns 0.
kis 0. The very first insert makes the set size 1, which is more than 0, so nothing is ever accepted.[1, 2, 3]withk = 0returns 0. A negativekbehaves the same way.kat least as large as the number of distinct values. The whole vector is valid:[1, 2, 3]withk = 5returns 3.- Counting elements instead of distinct values. The limit applies to different values, not to the subarray's length.
[5, 5, 5]withk = 1returns 3. - Updating the answer before the check. The length must be recorded only after the set is known to be within the limit, or invalid subarrays would be counted.
- Reusing one set across starts. Values from earlier subarrays would make the counts too high. Create the set inside the outer loop.
Testing
nums = [1, 2, 1, 2, 3],k = 2gives 4.nums = [1, 2, 3],k = 0gives 0.nums = [1, 2, 3],k = 5gives 3.nums = [5, 5, 5],k = 1gives 3.nums = [],k = 3gives 0.
