Longest Subarray With At Most Two Distinct Values
Solve this Problemnums, return the length of the longest contiguous subarray that contains at most 2 distinct values.
Checking every starting index and re-scanning forward works, but it forgets everything the previous start already learned about the array. The sliding windowSliding WindowMaintaining a running result over a contiguous range that grows or shrinks one element at a time, instead of recomputing the result for every range from scratch. technique keeps a frequency map of the values currently in view: grow the window by moving the right edge forward, and whenever a 3rd distinct value sneaks in, shrink from the left — dropping counts back to zero — until the window is valid again. Every element enters and leaves the window at most once, so the whole scan runs in O(n).
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 10⁵ - ◆
0 ≤ nums[i] ≤ 10⁴
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public int longestSubarrayWithAtMostTwoDistinct(int[] nums) { |
| 3 | Map<Integer, Integer> count = new HashMap<>(); |
| 4 | int left = 0, maxLen = 0; |
| 5 | for (int right = 0; right < nums.length; right++) { |
| 6 | count.put(nums[right], count.getOrDefault(nums[right], 0) + 1); |
| 7 | while (count.size() > 2) { |
| 8 | count.put(nums[left], count.get(nums[left]) - 1); |
| 9 | if (count.get(nums[left]) == 0) count.remove(nums[left]); |
| 10 | left++; |
| 11 | } |
| 12 | maxLen = Math.max(maxLen, right - left + 1); |
| 13 | } |
| 14 | return maxLen; |
| 15 | } |
| 16 | } |
| 17 |
00Start left at 0, maxLen at 0, and an empty frequency map of the values currently inside the window.
Approach & Solutions
Brute Force
BruteFor every possible starting index, grow the window to the right — tracking the set of distinct values seen — until a 3rd distinct value would enter, then record the window's length. Correct, but every start re-scans from scratch, throwing away everything the previous start already discovered about the array.
O(n²)O(1)1class Solution {
2 public int longestSubarrayWithAtMostTwoDistinct(int[] nums) {
3 int maxLen = 0;
4 for (int i = 0; i < nums.length; i++) {
5 Set<Integer> seen = new HashSet<>();
6 int j = i;
7 while (j < nums.length) {
8 seen.add(nums[j]);
9 if (seen.size() > 2) break;
10 j++;
11 }
12 maxLen = Math.max(maxLen, j - i);
13 }
14 return maxLen;
15 }
16}Optimal — Sliding Window
OptimalGrow the window by moving right and tracking a frequency map of the values inside it. Whenever the map holds more than 2 distinct keys, shrink from the left — decrementing counts and dropping keys that hit 0 — until it's valid again. Every value enters and leaves the window at most once, so the whole scan is O(n).
O(n)O(1)1class Solution {
2 public int longestSubarrayWithAtMostTwoDistinct(int[] nums) {
3 Map<Integer, Integer> count = new HashMap<>();
4 int left = 0, maxLen = 0;
5 for (int right = 0; right < nums.length; right++) {
6 count.put(nums[right], count.getOrDefault(nums[right], 0) + 1);
7 while (count.size() > 2) {
8 count.put(nums[left], count.get(nums[left]) - 1);
9 if (count.get(nums[left]) == 0) count.remove(nums[left]);
10 left++;
11 }
12 maxLen = Math.max(maxLen, right - left + 1);
13 }
14 return maxLen;
15 }
16}