Problem overview
The function longestSubarray receives a slice of integers, nums, and a limit k. It returns the length of the longest contiguous piece of nums that contains at most k different values. Repeats don't count twice: [1, 2, 1, 2] has only two distinct values even though it has four elements.
For nums = [1, 2, 1, 2, 3] and k = 2, the piece nums[0..3] = [1, 2, 1, 2] has two distinct values and length 4. Adding the 3 would make three distinct values, so the answer is 4.
The statement allows O(n²) time and O(n) extra space, which is enough for a direct approach with no clever window tricks.
Approach: try every start, extend until the limit is broken
Every subarray is determined by where it starts and where it ends. The lesson fixes the start i and then moves the end j to the right one element at a time, keeping the set of distinct values seen in nums[i..j].
The key observation is that growing a subarray can never reduce its number of distinct values. As soon as the set grows beyond k elements, every longer subarray with the same start is also invalid, so the inner loop can stop. Then the next start begins from scratch with an empty set.
That is two nested loops over at most n positions each, hence O(n²). Faster solutions exist that slide a window and never restart, but this lesson keeps the logic simple: for each start, find the longest valid end.
Take nums = [1, 2, 1, 2, 3] and k = 2. Starting at index 0, the set grows to {1}, {1, 2}, stays {1, 2} twice, and reaches three values at index 4, so the best length from this start is 4. Starting at index 1 gives [2, 1, 2], length 3. Starting at index 2 gives [1, 2], length 2, and so on. The maximum is 4.
Step by step
- Create
answer. It starts at 0, which is also the right result for an empty slice. - Loop over every start index
i. Each index is tried as the left end of a subarray. - Create a fresh set for this start. Declaring it inside the outer loop gives every start an empty one. Go has no set type, so the lesson uses a
map[int]struct{}: only the keys matter. - Loop over the end index
j, beginning ati, so the subarray starts with a single element and grows. - Add
nums[j]to the set. Storing a key that is already present changes nothing, solenof the map is always the number of distinct values. - Stop when the set is too large. If
len(distinctValues) > k,breakleaves only the inner loop; the outer loop moves on to the next start. - Record the length. Reaching this line means
nums[i..j]is valid, and its length isj - i + 1. Keep the larger of that andanswer. - Return
answerafter both loops are done.
The solution in Go
func longestSubarray(nums []int, k int) int {
answer := 0
for i := 0; i < len(nums); i++ {
distinctValues := make(map[int]struct{})
for j := i; j < len(nums); j++ {
distinctValues[nums[j]] = struct{}{}
if len(distinctValues) > k {
break
}
answer = max(answer, j-i+1)
}
}
return answer
}
Go details in this code
map[int]struct{}as a set. The empty structstruct{}occupies no memory, andstruct{}{}is its only value. Because the value carries no information, the map answers one question: is this key present?- Assigning an existing key is harmless. It overwrites the same empty value, so duplicates never inflate
len. maxis a built-in. Since Go 1.21 you don't need to write your own helper or import anything formaxandminon ordered types.breakonly leaves the innermostfor. That is exactly what the lesson wants here.- No
while. Both loops are the three-partforform.
Complexity
Time: O(n²). For each of the n starts, the inner loop runs at most n - i times, and each map insertion and len call takes constant time on average. The total number of steps is at most about n²/2.
Space: O(n). The map holds at most k + 1 distinct values before the break, and never more than n. A new map is created for every start, but the old one becomes garbage, so only one is alive at a time.
Edge cases and common mistakes
- Empty slice. Neither loop runs and the function returns 0.
k = 0. The first inserted value already makes the set size 1, which is more than 0, so every inner loop breaks immediately and the answer is 0. Withnums = [5, 5, 5]andk = 0the result is 0.- All values equal. The set never grows beyond one value, so for any
k >= 1the answer islen(nums). - Reusing one map for all starts. If the map is declared before the outer loop, values from earlier starts stay in it and the counts come out too high. The map must be created inside the outer loop.
- Updating
answerbefore the check. The length is recorded only after theif; otherwise an invalid subarray could be counted. - Counting elements instead of distinct values. Comparing the subarray length to
kis wrong:[1, 2, 1, 2]has length 4 but only two distinct values.
Testing
nums = [1, 2, 1, 2, 3],k = 2gives 4.nums = [1, 2, 3],k = 1gives 1.nums = [],k = 2gives 0.