Master this topic with zero to advance depth.
The Sliding Window technique is a powerful optimization used to convert O() or O() nested loop problems into O() linear time. It is primarily used for contiguous subarrays or substrings.
The window size k is constant. We slide the window by adding one element from the right and removing one from the left.
Window Size K=3, nums = [1, 2, 3, 4, 5, 6]
Step 1: [1, 2, 3], 4, 5, 6 (Sum: 6)
Step 2: 1, [2, 3, 4], 5, 6 (Sum: 9)
Step 3: 1, 2, [3, 4, 5], 6 (Sum: 12)The window size expands and shrinks based on a condition. We use two pointers: left and right.
Target Sum >= 7, nums = [2, 3, 1, 2, 4, 3]
[2, 3, 1], 2, 4, 3 (Sum: 6 < 7, Expand Right)
[2, 3, 1, 2], 4, 3 (Sum: 8 >= 7, Valid! Shrink Left)
2, [3, 1, 2], 4, 3 (Sum: 6 < 7, Expand Right)Most variable window problems follow this structure:
def sliding_window(nums):
left = 0
state = initial_state()
res = 0
for right in range(len(nums)):
# 1. Expand: Update state with nums[right]
update_state(state, nums[right])
# 2. Shrink: While condition is violated
while condition_violated(state):
remove_from_state(state, nums[left])
left += 1
# 3. Update Result: Window is now valid
res = max(res, right - left + 1)
return resSum variable for numeric problems, a HashMap for character frequency, or a Deque for window maximums.count > K. For "Exactly K", calculate atMost(K) - atMost(K-1).Sum variable is a 64-bit integer (e.g., long in Java/C++).n < k or the input is empty.Maximum Sum Subarray of Size K
Given an array of integers nums and a positive integer k, find the maximum sum of any contiguous subarray of size k.
nums = [2, 1, 5, 1, 3, 2], k = 3
Step 1: [2, 1, 5], 1, 3, 2 (Sum = 8)
Step 2: 2, [1, 5, 1], 3, 2 (Sum = 7)
Step 3: 2, 1, [5, 1, 3], 2 (Sum = 9) -> MAX
Step 4: 2, 1, 5, [1, 3, 2] (Sum = 6)Examples
Subarray [5, 1, 3] has the maximum sum of 9.
Intuition
The most basic way to solve this is to check every possible contiguous subarray of size k and calculate its sum. We keep track of the maximum sum found so far.
i from 0 to n - k.i, start another loop to sum up the next k elements.maxSum if the current subarray sum is larger.This is a Naive Search pattern. We are re-calculating the sum for overlapping parts of subarrays, which is the main bottleneck.
Detailed Dry Run
| Outer Loop (i) | Inner Loop (j) | Current Sum | Max Sum | Action |
|---|---|---|---|---|
| 0 | 0, 1, 2 | 2+1+5 = 8 | 8 | Init Max |
| 1 | 1, 2, 3 | 1+5+1 = 7 | 8 | No Change |
| 2 | 2, 3, 4 | 5+1+3 = 9 | 9 | Update Max |
| 3 | 3, 4, 5 | 1+3+2 = 6 | 9 | No Change |
Intuition
We can precompute a prefix sum array where prefix[i] stores the sum of elements from 0 to i-1. The sum of any subarray nums[i...j] can then be calculated in as prefix[j+1] - prefix[i].
prefix of size n + 1.prefix such that prefix[i+1] = prefix[i] + nums[i].i = 0 to n - k and calculate sum = prefix[i+k] - prefix[i].maxSum accordingly.This approach reduces the calculation time to per subarray but uses extra space.
Intuition
We can observe that two consecutive subarrays of size k share k-1 elements. Instead of re-summing everything, we can 'slide' the window: add the next element (Right) and subtract the element that is no longer in the window (Left).
nums[right] to windowSum.right >= k - 1, the window is full. Update the result, then subtract nums[left] and increment left to prepare for the next step.left: Pointer to the start of the window.windowSum: Current sum of the k elements.maxSum: Best sum found so far.Detailed Dry Run
| Step | Right | Left | windowSum | maxSum | Action |
|---|---|---|---|---|---|
| 1 | 0 | 0 | 2 | 0 | Expand |
| 2 | 1 | 0 | 3 | 0 | Expand |
| 3 | 2 | 0 | 8 | 8 | Window Full, Update Max |
| 4 | 3 | 1 | 7 | 8 | Slide (Sub 2, Add 1) |
| 5 | 4 | 2 | 9 | 9 | Slide (Sub 1, Add 3), Update Max |
Minimum Size Subarray Sum
Given an array of positive integers nums and a positive integer target, return the minimal length of a contiguous subarray of which the sum is greater than or equal to target. If there is no such subarray, return 0 instead.
target = 7, nums = [2, 3, 1, 2, 4, 3]
[2, 3, 1, 2], 4, 3 (Sum: 8 >= 7, Len: 4)
2, [3, 1, 2, 4], 3 (Sum: 10 >= 7, Len: 4)
2, 3, 1, [2, 4, 3] (Sum: 9 >= 7, Len: 3) -> MINIMALExamples
The subarray [4,3] has the minimal length under the problem constraint.
Intuition
Check all possible subarrays and find the one with sum >= target and minimum length.
nums[i...j].sum >= target, update minLen = min(minLen, j - i + 1).Intuition
This is the classic Variable Size Window problem. We expand the window until the sum meets the target, then shrink from the left to find the smallest valid window.
windowSum and a left pointer.right from 0 to n-1 (Expand).nums[right] to windowSum.windowSum >= target:
minLen with right - left + 1.nums[left] from windowSum and increment left (Shrink).left: Pointer to the start of the window.windowSum: Current sum of the window content.minLen: Smallest valid window length found.Detailed Dry Run
| Step | L | R | windowSum | minLen | Action |
|---|---|---|---|---|---|
| 1 | 0 | 0 | 2 | inf | Expand |
| 2 | 0 | 1 | 5 | inf | Expand |
| 3 | 0 | 2 | 6 | inf | Expand |
| 4 | 0 | 3 | 8 | 4 | Sum >= 7! Update minLen, Shrink L |
| 5 | 1 | 3 | 6 | 4 | Sum < 7. Expand R |
Longest Substring Without Repeating Characters
Given a string s, find the length of the longest substring without repeating characters.
s = "abcabcbb"
L R
| |
a b c a b c b b
[---] Set: {a, b, c}, Len: 3
L R
| |
a b c a b c b b
[---] Set: {b, c, a}, Len: 3Examples
The answer is "abc", with the length of 3.
Intuition
Check every possible substring and verify if it contains unique characters. A string of length has substrings. Checking each takes , leading to . We can optimize the check using a Set to .
s[i...j].maxLength.Detailed Dry Run
| i | j | Substring | Unique? | Max Len |
|---|---|---|---|---|
| 0 | 0 | "a" | Yes | 1 |
| 0 | 1 | "ab" | Yes | 2 |
| 0 | 2 | "abc" | Yes | 3 |
| 0 | 3 | "abca" | No | 3 |
| 1 | 3 | "bca" | Yes | 3 |
Intuition
We can binary search for the maximum length k. For a fixed k, we check if there exists any substring of length k with no repeating characters using a fixed-size sliding window. If a valid substring of length k exists, then any length smaller than k is also possible, so we search in [k, right]. Otherwise, we search in [left, k-1].
[1, n].mid):
mid to check for uniqueness.ans = mid, low = mid + 1.high = mid - 1.Intuition
This is a Variable Size Window problem because the length of the unique substring changes as we encounter duplicates.
Instead of checking all substrings, we maintain a sliding window [left, right]. As we expand right, we add the character to a Set. If s[right] is already in the Set, we have a violation. We must shrink the window from the left until the duplicate is gone.
left: Marks the start of the current unique substring.charSet: Stores characters in the current window for duplicate checking.maxLength: Tracks the largest window size found.Detailed Dry Run
| Step | L | R | Char | Action | Set Content | Max Len |
|---|---|---|---|---|---|---|
| 1 | 0 | 0 | 'a' | Add 'a' | {a} | 1 |
| 2 | 0 | 1 | 'b' | Add 'b' | {a, b} | 2 |
| 3 | 0 | 2 | 'c' | Add 'c' | {a, b, c} | 3 |
| 4 | 0 | 3 | 'a' | Dupe 'a'! Shrink L | {b, c, a} | 3 |
| 5 | 1 | 4 | 'b' | Dupe 'b'! Shrink L | {c, a, b} | 3 |
⚠️ Common Pitfalls & Tips
Be careful with the window shrink condition. It must be a while loop to remove all characters until the duplicate is gone. Also, remember to add the current character after the shrink loop.
Permutation in String
Given two strings s1 and s2, return true if s2 contains a permutation of s1, or false otherwise.
s1 = "ab", s2 = "eidbaooo"
Target Count: {a:1, b:1}
[e, i] d b a o o o Count: {e:1, i:1} (Mismatch)
e [i, d] b a o o o Count: {i:1, d:1} (Mismatch)
e i [d, b] a o o o Count: {d:1, b:1} (Mismatch)
e i d [b, a] o o o Count: {b:1, a:1} (Matches!)Examples
s2 contains one permutation of s1 ("ba").
Intuition
To check if s2 contains a permutation of s1, we can generate all substrings of s2 that have the same length as s1, and then check if that substring is a permutation of s1 (by sorting both and comparing).
s2 with length equal to s1.length().s1.Detailed Dry Run
| Window in s2 | Sorted Window | Sorted s1 (ab) | Match? |
|---|---|---|---|
| "ei" | "ei" | "ab" | No |
| "id" | "di" | "ab" | No |
| "db" | "bd" | "ab" | No |
| "ba" | "ab" | "ab" | YES |
Intuition
Instead of sorting, we can compare character frequency maps. This is still a 'sliding' concept but we re-build or re-check the entire map of size 26 for each window. Since the alphabet size is constant (26), this is technically O(N * 26).
s1.s2 and for every window of size s1.length(), build a new frequency map.s1's map.Intuition
This is a Fixed Size Window problem because any permutation of s1 must have exactly the same length as s1.
Instead of sorting every substring, we use character frequency counts. A permutation of s1 will have the exact same character frequency count as s1. We maintain a window of size s1.length() in s2 and update the counts as we slide.
left: Marks the start of the window.s1Counts: Frequency map of characters in s1.windowCounts: Frequency map of characters in the current s2 window.Detailed Dry Run
| Window | s2 Fragment | Counts Match? | Action |
|---|---|---|---|
| [0, 1] | "ei" | No | Expand R, Shrink L |
| [1, 2] | "id" | No | Expand R, Shrink L |
| [2, 3] | "db" | No | Expand R, Shrink L |
| [3, 4] | "ba" | YES! | Return True |
⚠️ Common Pitfalls & Tips
Be careful to check the final window after the loop ends, as the last comparison might not happen inside the loop depending on how you structure it.
Minimum Window Substring
Given two strings s and t, return the minimum window substring of s such that every character in t (including duplicates) is included in the window.
s = "ADOBECODEBANC", t = "ABC"
Window Expand (Found all ABC):
[ADOBEC]ODEBANC (Len: 6)
Window Shrink (Still have ABC):
A [DOBEC]ODEBANC (Len: 5) -> [DOBEC] (Wait, missing A!)
Final Optimal Window:
ADOBECODE [BANC] (Len: 4)Examples
Intuition
Check every possible substring of s and verify if it contains all characters of t in the required frequencies. Keep track of the minimum length substring that satisfies this.
start and end indices to define every substring.t.minWindow result.Detailed Dry Run
| Substring | Valid? | Min Length | Min Window |
|---|---|---|---|
| "ADOBE" | No (missing C) | inf | "" |
| "ADOBEC" | YES! | 6 | "ADOBEC" |
| "BANC" | YES! | 4 | "BANC" |
Intuition
The shortest valid window length must be between len(t) and len(s). We can binary search for this length k. For each k, we use a fixed-size sliding window of length k to check if any valid substring exists. If it does, we try smaller lengths; otherwise, we try larger ones.
Detailed Dry Run
Input: s = "ADOBECODEBANC", t = "ABC"
[3, 13].k = 8: Substring ADOBECOD is valid. Search [3, 7].k = 5: Substring EBANC is valid. Search [3, 4].k = 4: Substring BANC is valid. Search [3, 3].k = 3: No window of size 3 is valid.k = 4, return BANC.Intuition
This is a Variable Size Window problem. We need to find the smallest range [L, R] that satisfies the requirement.
targetCounts to store required characters in t.right until the window contains all characters in t. We use a have counter vs a need counter for validity check.left as much as possible while maintaining validity to find the smallest window.minWindow result whenever a smaller valid window is found.left, right: Window pointers.targetMap: Frequencies of characters in t.windowMap: Frequencies of characters in the current window.have, need: Variables to track progress toward the target frequency.Detailed Dry Run
s = "ADOBEC", t = "ABC"
| Step | L | R | Char | Window Map | Have/Need | Action |
|---|---|---|---|---|---|---|
| 1 | 0 | 0 | 'A' | {A:1} | 1/3 | Expand |
| 2-4 | 0 | 4 | 'E' | {A:1, B:1} | 2/3 | Expand |
| 5 | 0 | 5 | 'C' | {A:1, B:1, C:1} | 3/3 | VALID! |
| 6 | 1 | 5 | 'D' | {B:1, C:1} | 2/3 | Shrink (Invalidated) |
⚠️ Common Pitfalls & Tips
Be careful with character counts if t has duplicates. Using a have/need counter for unique characters is more robust than a total character count.
Max Consecutive Ones III
Given a binary array nums and an integer k, return the maximum number of consecutive 1's in the array if you can flip at most k 0's.
nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2
L R
| |
1 1 1 0 0 0 1 1 1 1 0
[-----] (Zeros: 1 <= 2, Expand R)
L R
| |
1 1 1 0 0 0 1 1 1 1 0
[-------] (Zeros: 2 <= 2, Expand R)
L R
| |
1 1 1 0 0 0 1 1 1 1 0
[---------] (Zeros: 3 > 2! Shrink L)Examples
Intuition
Check every possible subarray and count the number of zeros in it. If the zero count is less than or equal to k, the subarray is valid. Keep track of the maximum length of such valid subarrays.
[i, j].zeros <= k, update maxLen = max(maxLen, j - i + 1).zeros > k, break the inner loop (optimization).Detailed Dry Run
| i | j | nums[j] | Zeros | Max Len | Action |
|---|---|---|---|---|---|
| 0 | 0 | 1 | 0 | 1 | Update |
| 0 | 3 | 0 | 1 | 4 | Update |
| 0 | 4 | 0 | 2 | 5 | Update |
| 0 | 5 | 0 | 3 | 5 | Break (Zeros > k) |
Intuition
We can binary search for the maximum possible length L of a valid subarray. For a fixed length L, we can check if there exists any subarray of length L with at most k zeros using a fixed-size sliding window in time.
[0, n].mid length:
mid across the array.zeros <= k, then mid is possible.Intuition
Instead of checking every subarray, we use a window [left, right]. We expand the window by moving right. If the number of zeros in the window exceeds k, we must shrink the window from the left until the zero count is back to k.
windowSum += (nums[right] == 0 ? 1 : 0)zeros > kwhile (zeros > k) { if (nums[left] == 0) zeros--; left++; }Detailed Dry Run
| R | Num | Zeros | Action | Max Len |
|---|---|---|---|---|
| 3 | 0 | 1 | Expand | 4 |
| 4 | 0 | 2 | Expand | 5 |
| 5 | 0 | 3 | Shrink L (until zeros=2) | 5 |
| 10 | 0 | 2 | Expand | 6 |
⚠️ Common Pitfalls & Tips
Be careful with the while loop condition. It should be zeros > k. Also, ensure you update maxLen after the shrink loop is done to ensure the window is valid.
Fruit Into Baskets
You are visiting a farm that has a single row of fruit trees. Each tree has a type. You have TWO baskets, each holding ONE type. Find the maximum fruits you can collect in a contiguous range.
fruits = [1, 2, 1, 2, 3]
L R
| |
1, 2, 1, 2, 3 Types: {1, 2}, Count: 4
[---------]
L R
| |
1, 2, 1, 2, 3 Types: {2, 3}, Count: 2
[-]Examples
Intuition
Check every possible contiguous range of trees and count how many fruits and types are in that range. If the number of types is ≤ 2, the range is valid. Track the maximum fruits collected.
[i, j].maxFruits = max(maxFruits, j - i + 1).Detailed Dry Run
| i | j | fruits[j] | Types | Fruits | Max |
|---|---|---|---|---|---|
| 0 | 0 | 1 | {1} | 1 | 1 |
| 0 | 1 | 2 | {1, 2} | 2 | 2 |
| 0 | 2 | 1 | {1, 2} | 3 | 3 |
| 0 | 3 | 2 | {1, 2} | 4 | 4 |
| 0 | 4 | 3 | {1, 2, 3} | 5 | 4 (Break) |
Intuition
We can binary search for the maximum number of fruits L we can collect. For a fixed length L, we check if any contiguous subarray of length L contains at most 2 distinct fruit types using a fixed-size sliding window.
[1, n].mid length:
mid.map.size() <= 2 at any point, the length mid is possible.Intuition
We need to find the longest subarray that contains exactly or at most two distinct elements. We use a frequency map to track the fruits in our window. When the number of types (map size) exceeds 2, we shrink the window from the left.
count[fruits[right]]++count.size() > 2while (count.size() > 2) { count[fruits[left]]--; if (count[fruits[left]] == 0) count.remove(fruits[left]); left++; }Detailed Dry Run
| R | Fruit | Map | Map Size | Action | Result |
|---|---|---|---|---|---|
| 0 | 1 | {1:1} | 1 | Expand | 1 |
| 1 | 2 | {1:1, 2:1} | 2 | Expand | 2 |
| 2 | 1 | {1:2, 2:1} | 2 | Expand | 3 |
| 3 | 2 | {1:2, 2:2} | 2 | Expand | 4 |
| 4 | 3 | {1:2, 2:2, 3:1} | 3 | Shrink L (remove 1s) | 4 |
⚠️ Common Pitfalls & Tips
Be careful with shrinking: ensure you decrement the count and remove the key from the map ONLY when the count reaches zero. Forgetting to remove the key will result in an incorrect count.size().
Longest Repeating Character Replacement
You are given a string s and an integer k. You can change at most k characters to any other uppercase English character. Return the length of the longest substring containing the same letter.
s = "AABABBA", k = 1
[A A B A] B B A (Len: 4, MaxFreq char 'A': 3)
Window Size 4 - MaxFreq 3 = 1 (Matches k=1, VALID)
[A A B A B] B A (Len: 5, MaxFreq char 'A': 3)
Window Size 5 - MaxFreq 3 = 2 (Exceeds k=1, INVALID)Examples
Replace the two 'A's with two 'B's or vice-versa.
Intuition
For every possible substring, check if we can make all characters in that substring the same by replacing at most k characters. To do this for a substring, we find the frequency of the most common character and check if (length - maxFreq) <= k.
[i, j].maxFreq).(substringLength - maxFreq) <= k, the substring is valid.maxLen accordingly.Detailed Dry Run
| Substring | Freq Map | Max Freq | Len - MaxFreq | k | Valid? |
|---|---|---|---|---|---|
| "AAB" | {A:2, B:1} | 2 | 3-2 = 1 | 1 | YES |
| "AABA" | {A:3, B:1} | 3 | 4-3 = 1 | 1 | YES |
| "AABAB" | {A:3, B:2} | 3 | 5-3 = 2 | 1 | NO |
Intuition
We can binary search for the maximum possible length L of a valid substring. For a fixed length L, we use a sliding window of size L to check if at least one window satisfies (L - maxFreq) <= k. Finding maxFreq in a window takes O(26).
L is [0, n].mid length step in binary search:
mid across the string.mid - maxFreq <= k, then length mid is possible.Intuition
Instead of re-calculating everything, we use a sliding window [left, right]. We maintain the frequency of the most common character within the current window. The window is valid as long as (WindowLength - MaxFrequency) <= k. This works because WindowLength - MaxFrequency represents the minimum number of characters we need to replace to make all characters in the window the same.
s[right] and update maxFreq.(right - left + 1) - maxFreq > kleft and decrement its frequency. Note: maxFreq doesn't strictly need to be decreased, as only a larger maxFreq can increase our result.Detailed Dry Run
| R | Char | Freq Map | Max Freq | Valid? | Action |
|---|---|---|---|---|---|
| 0 | A | {A:1} | 1 | Yes | Expand |
| 1 | A | {A:2} | 2 | Yes | Expand |
| 2 | B | {A:2, B:1} | 2 | Yes | Expand |
| 3 | A | {A:3, B:1} | 3 | Yes | Expand |
| 4 | B | {A:3, B:2} | 3 | No | Shrink L |
⚠️ Common Pitfalls & Tips
You don't need to decrement maxFreq when shrinking the window. While this seems counter-intuitive, think about it: we only care about the largest maxFreq we've ever seen because that's the only way to get a larger maxLen.
Find All Anagrams in a String
Given strings s and p, return an array of all the start indices of p's anagrams in s.
s = "cbaebabacd", p = "abc"
[c b a] e b a b a c d (Window: {a:1, b:1, c:1}, Matches! Index 0)
c [b a e] b a b a c d (Window: {a:1, b:1, e:1}, Mismatch)
...
c b a e b a b [a c d] (Wait, missing b! Mismatch)Examples
Intuition
For every possible substring of s that has the same length as p, check if it's an anagram of p. To check for anagrams, we can sort both strings or compare their character frequency maps.
s with a loop from 0 to n - m (where m is p.length()).m.p using a frequency map or sorting.Detailed Dry Run
| Start Index | Substring | Is Anagram of "abc"? | Result |
|---|---|---|---|
| 0 | "cba" | YES | [0] |
| 1 | "bae" | NO | [0] |
| 6 | "abc" | YES | [0, 6] |
Intuition
Instead of re-comparing the whole substring or sorting, we can compare the frequency counts of characters. Since the alphabet is small (26), comparing two maps of size 26 is , which is effectively constant time.
p.s and for every window of size m, build the frequency map for that window.pCount using Arrays.equals (Java) or == (Python/Go).Intuition
Since an anagram must have exactly the same length as p, we use a Fixed Size Sliding Window of length m. We maintain frequency counts for both p and the current s window. Instead of re-calculating the frequency map for every window, we 'slide' it: add the incoming character and remove the outgoing one.
p and the first m characters of s.i from m to n-1:
s[i] to sCount.s[i - m] from sCount.Detailed Dry Run
| Window | Start Index | Added | Removed | Match? | | :--- | :--- | :--- | :--- | :--- | :--- | | [0, 2] | 0 | - | - | YES | | [1, 3] | 1 | 'e' | 'c' | NO | | [6, 8] | 6 | 'c' | 'b' | YES |
⚠️ Common Pitfalls & Tips
Be careful with the sliding logic: ensure you add the NEW character and remove the OLD character at the same step to keep the window size constant. Also, check the very first window before the loop starts.
Sliding Window Maximum
Given an array nums and a window size k, return the maximum in each sliding window.
nums = [1, 3, -1, -3, 5, 3, 6, 7], k = 3
Window: [1, 3, -1] Max: 3
Window: [3, -1, -3] Max: 3
Window: [-1, -3, 5] Max: 5
Monotonic Deque (indices):
Step 1 (1): [0]
Step 2 (3): [1] (discarded 0 since 3 > 1)
Step 3 (-1): [1, 2]
Step 4 (-3): [1, 2, 3]
Step 5 (5): [4] (discarded 1, 2, 3 since 5 is larger)Examples
Intuition
For every possible sliding window of size k, iterate through all its elements to find the maximum value.
n - k + 1 windows in an array of size n.i, loop from i to i + k - 1 to find the max.Detailed Dry Run
| Window | Elements | Max | Result |
|---|---|---|---|
| [0, 2] | [1, 3, -1] | 3 | [3] |
| [1, 3] | [3, -1, -3] | 3 | [3, 3] |
| [2, 4] | [-1, -3, 5] | 5 | [3, 3, 5] |
Intuition
To find the maximum in a window efficiently, we can use a Max-Heap (Priority Queue). The heap stores pairs of (value, index). For each window, we add the current element to the heap and then remove elements from the top of the heap if their indices are outside the current window.
[nums[i], i].i - k + 1, it's outside the window; remove it (pop).Intuition
We need a way to find the maximum in the current window in . A Monotonic Deque stores indices of elements in strictly decreasing order of their values (nums[dq.front()] is always max).
[i-k+1, i], remove it.nums[i], remove all indices from the back whose values are . They can never be the maximum in any future window containing nums[i].k, the value at nums[dq.front()] is the maximum for the current window.Detailed Dry Run
| i | Val | Action | Deque (Indices) | Result |
|---|---|---|---|---|
| 1 | 3 | Pop 0 (1 < 3) | [1] | - |
| 2 | -1 | Push 2 | [1, 2] | [3] |
| 3 | -3 | Push 3 | [1, 2, 3] | [3, 3] |
| 4 | 5 | Pop all (all < 5) | [4] | [3, 3, 5] |
⚠️ Common Pitfalls & Tips
Storing values instead of indices in the deque makes it hard to check if the maximum element has slid out of the window. Always store indices.
Minimum Window Subsequence
Given strings s1 and s2, find the minimum contiguous substring of s1 such that s2 is a subsequence of that part.
s1 = "abcdebdde", s2 = "bde"
Forward (Find b...d...e):
a b c d e b d d e
^ ^ ^ (Found at index 4, end=5)
Backward (Optimize Start from index 4):
a b c d e
^ ^ (Start=1, b is at idx 1)
Result: "bcde" (Len 4)Examples
Intuition
For every possible starting point in s1, scan forward to see if s2 can be formed as a subsequence. If it can, record the length and update the minimum window found so far.
i in s1 as potential starts.i, use another pointer k to scan s1, and j to scan s2.s1[k] == s2[j], increment j.j == s2.length(), we found a window [i, k]. Its length is k - i + 1.Detailed Dry Run
| Start | s1 Scan | s2 Matched | Window | Min |
|---|---|---|---|---|
| 1 (b) | bcde | b, d, e (All) | [1, 4] | 4 |
| 5 (b) | bdde | b, d, e (All) | [5, 8] | 4 |
Intuition
We can use a 2D DP table dp[i][j] that stores the starting index of the shortest substring in s1[0...i] such that s2[0...j] is a subsequence. If no such substring exists, we store -1.
dp[i][0] is i if s1[i] == s2[0], else dp[i-1][0].j > 0, if s1[i] == s2[j], then dp[i][j] = dp[i-1][j-1] (we extend the subsequence start index from the previous match).dp[i][j] = dp[i-1][j] (we inherit the latest start index).Intuition
Unlike 'Minimum Window Substring' (set of chars), this requires subsequence (specific order). We scan forward to find any window containing the subsequence. Once found, we scan backward from the current end to find the best starting point for that specific window.
i.i, scan back to find the latest valid start j. This handles cases like S=abbbcde, T=abcde more accurately by skipping redundant bs at the beginning of the window.Detailed Dry Run
| i | j | Action | Result |
|---|---|---|---|
| 1 | 0 | 'b' matched | i=2, j=1 |
| 4 | 2 | 'e' matched | Window Found! |
| Backward | - | Scan back from i=4 | Start=1 |
| Min | - | Check "bcde" | MinLen=4 |
⚠️ Common Pitfalls & Tips
The backward scan is crucial for finding the optimal start. Without it, you might find a valid window but not the minimum one starting from a later occurrence of the first character.
Maximum Points You Can Obtain from Cards
You can take exactly k cards from either the beginning or the end of the row to maximize your point total.
cardPoints = [1, 2, 3, 4, 5, 6, 1], k = 3
Take cards from ends (Total: 7, k: 3):
(1, 2) ... (1) Total: 4
(1) ... (6, 1) Total: 8
... ... (5, 6, 1) Total: 12 (MAX)
Trick: Minimize the sum of the remaining (n-k) cards!
Remaining window size = 7 - 3 = 4Examples
Intuition
Try all possible combinations of taking i cards from the left and k - i cards from the right (where 0 <= i <= k). For each combination, calculate the sum and track the maximum.
i be the number of cards from the left end.k - i cards must be taken from the right end.i from 0 to k.Sum = (Sum of first i) + (Sum of last k - i).Detailed Dry Run
| Cards from Left | Cards from Right | Total Sum |
|---|---|---|
| 0 | 3 (5, 6, 1) | 12 |
| 1 (1) | 2 (6, 1) | 8 |
| 2 (1, 2) | 1 (1) | 4 |
| 3 (1, 2, 3) | 0 | 6 |
Intuition
Selecting k cards from the ends is equivalent to leaving n - k contiguous cards in the middle. To maximize the end cards, we must minimize the sum of the middle cards. This turns it into a fixed-size sliding window problem on the inner subarray.
n - k.Detailed Dry Run
| Window | Sum | Min Sum | Action |
|---|---|---|---|
| [1, 2, 3, 4] | 10 | 10 | Initial |
| [2, 3, 4, 5] | 14 | 10 | Slide |
| [3, 4, 5, 6] | 18 | 10 | Slide |
| [4, 5, 6, 1] | 16 | 10 | Slide |
⚠️ Common Pitfalls & Tips
While you can use recursion with memoization, the sliding window approach is much faster and uses O(1) extra space. The 'inverse' trick is the most important leap.
Longest Subarray of 1's After Deleting One Element
Given a binary array nums, you must delete exactly one element. Return the maximum number of consecutive 1's remaining.
nums = [1, 1, 0, 1]
[1, 1, 0, 1]
^ Delete this 0
Remaining: [1, 1, 1] -> Len 3
Sliding Window Rule:
Window must contain at most ONE zero.
Final Result = WindowSize - 1Examples
Intuition
Iterate through every element in the array. For each element, assume it is the one being deleted, and then find the longest contiguous block of 1's that can be formed using the remaining elements.
i from 0 to n-1.nums[i].Detailed Dry Run
| Deleting Index | Resulting Array | Max 1s | Result |
|---|---|---|---|
| 0 | [1, 0, 1] | 1 | 1 |
| 1 | [1, 0, 1] | 1 | 1 |
| 2 | [1, 1, 1] | 3 | 3 |
| 3 | [1, 1, 0] | 2 | 3 |
Intuition
This is equivalent to 'Max Consecutive Ones III' with k = 1. We find the longest window with at most one zero. Since we must delete one element, the result is always WindowSize - 1.
zeros > 1, shrink from left.Detailed Dry Run
| R | Num | Zeros | Window Size | Result |
|---|---|---|---|---|
| 0 | 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 2 | 1 |
| 2 | 0 | 1 | 3 | 2 |
| 3 | 1 | 1 | 4 | 3 (MAX) |
⚠️ Common Pitfalls & Tips
If the array consists only of 1's, the result should be N - 1, not N. Don't forget that one deletion is MANDATORY.
Minimum Operations to Reduce X to Zero
Subtract values from either the left or right to reduce x exactly to 0. Return the minimum operations.
nums = [1, 1, 4, 2, 3], x = 5
[1, 1] ... [3] (Total: 5, Ops: 3)
[1] ... [2, 3] (Total: 6, Ops: 3) X
... ... [2, 3] (Total: 5, Ops: 2) -> BEST
Goal: Maximize middle subarray with sum (TotalSum - x)
Middle Target = 11 - 5 = 6
Max Middle = [1, 1, 4] (Len 3)
Ops = 5 - 3 = 2Examples
Intuition
Iterate through all possible numbers of elements taken from the left end (i elements). For each i, find out how many elements from the right end are needed to reach exactly x. Track the minimum total operations.
i be the number of elements from the left (0 <= i <= nums.length).i elements. If sum > x, we can't take this many from left.sum <= x, we need to find x - sum from the right end.i + count_from_right.Detailed Dry Run
| Left Ops | Left Sum | Target Right | Right Ops | Total |
|---|---|---|---|---|
| 0 | 0 | 5 | 2 (2, 3) | 2 |
| 1 (1) | 1 | 4 | 0 (None) | - |
| 2 (1, 1) | 2 | 3 | 1 (3) | 3 |
Intuition
Finding minimum operations from the ends is the same as finding the maximum length contiguous subarray in the middle whose sum is totalSum - x. This simplifies the problem into a standard variable-size sliding window.
Sum(nums) - x.TotalLength - MaxWindowLength.Detailed Dry Run
| Current Sum | Target | Max Len | Ops |
|---|---|---|---|
| 1 | 6 | - | - |
| 2 | 6 | - | - |
| 6 (Found!) | 6 | 3 | 5-3=2 |
| 8 | 6 | 3 | - |
⚠️ Common Pitfalls & Tips
Edge cases: x is larger than total sum (target < 0), or x is exactly the total sum (target = 0). Use long for sums to avoid overflow if arrays are very large.
Grumpy Bookstore Owner
A bookstore owner can be grumpy at certain minutes. You can use a 'secret technique' to keep them calm for minutes consecutive minutes. Maximize satisfied customers.
customers = [1, 0, 1, 2, 1, 1, 7, 5]
grumpy = [0, 1, 0, 1, 0, 1, 0, 1]
minutes = 3
Base satisfaction (owner not grumpy): 1 + 1 + 1 + 7 = 10
Potential extra (using technique on window of size 3):
Win [1, 2, 1] (mins 1-3) -> Extra: 0*c[1] + 1*c[2] + 0*c[3] = 2
Win [7, 5] (mins 6-7) -> ... finding max extra ...Examples
Intuition
Iterate through every possible starting minute i for the 'X-minute technique'. For each i, calculate the total satisfied customers by summing: (base satisfied customers) + (additional customers satisfied while the technique is active at i).
BaseSatisfied: Sum of customers[j] where grumpy[j] == 0 for all j.i from 0 to n - minutes.i, calculate Additional: Sum of customers[j] where grumpy[j] == 1 and i <= j < i + minutes.BaseSatisfied + max(Additional).Detailed Dry Run
| Start | Base | Additional | Total |
|---|---|---|---|
| 0 | 10 | 1+1+0 | 12 |
| 3 | 10 | 2+1+1 | 14 |
| 5 | 10 | 1+5+0 | 16 (MAX) |
Intuition
We want to choose a window of size minutes where we 'cancel' the owner's grumpiness to maximize additional customers. This is a classic fixed-size sliding window over the potential 'bonuses'.
minutes.Detailed Dry Run
| Window | Recovered | Max Recovered |
|---|---|---|
| [1,0,1] | 0 | 0 |
| [0,1,2] | 3 | 3 |
| [1,2,1] | 3 | 3 |
| [1,1,7] | 8 | 8 (MAX) |
⚠️ Common Pitfalls & Tips
Ensure you only add/remove customers[i] based on grumpy[i] == 1. The base customers grumpy[i] == 0 should not be affected by the sliding window logic after they are counted initially.
Maximum Number of Vowels in a Substring of Given Length
Find the maximum number of vowels in any substring of length k.
s = "abciiidef", k = 3
Window [abc] -> Vowels: 1 (a)
Window [bci] -> Vowels: 1 (i)
Window [cii] -> Vowels: 2 (i, i)
Window [iii] -> Vowels: 3 (i, i, i) -> MAXExamples
Intuition
Iterate through all possible strings of length k. For each substring, count the number of vowels manually by iterating through characters.
i from 0 to n - k.s[i : i+k].Detailed Dry Run
| Substring | Vowels | Max |
|---|---|---|
| abc | a (1) | 1 |
| bci | i (1) | 1 |
| cii | i, i (2) | 2 |
| iii | i, i, i (3) | 3 |
Intuition
We can precompute an array vowelCount where vowelCount[i] stores the number of vowels from index 0 to i-1. The number of vowels in any substring s[i...i+k-1] can be calculated as vowelCount[i+k] - vowelCount[i].
prefix of size n + 1.s[i] is a vowel, prefix[i+1] = prefix[i] + 1, otherwise prefix[i+1] = prefix[i].i from 0 to n - k and track max(prefix[i+k] - prefix[i]).Intuition
This is a classic fixed-size sliding window problem. We maintain a count of vowels. When a new character enters the window, we increment if it's a vowel. When a character leaves, we decrement if it was a vowel.
k: Window is always exactly k wide.Detailed Dry Run
| Window | Vowel Count | Max Count |
|---|---|---|
| [abc] | 1 | 1 |
| [bci] | 1 | 1 |
| [cii] | 2 | 2 |
| [iii] | 3 | 3 |
⚠️ Common Pitfalls & Tips
Be careful with string indexing. The check for leaving elements should happen once the index i is >= k.
Subarray Product Less Than K
Count the number of contiguous subarrays where the product of all elements is strictly less than k.
nums = [10, 5, 2, 6], k = 100
[10] -> Prod: 10 (<100) Count +1
[10, 5] -> Prod: 50 (<100) Count +2 (new: [5], [10,5])
[10, 5, 2] -> Prod: 100 (>=100) -> Shrink left
[5, 2] -> Prod: 10 (<100) Count +2 (new: [2], [5,2])
Rule: Subarrays ending at 'right' = right - left + 1Examples
Intuition
Iterate through every possible starting point i and ending point j. For each pair, calculate the product of elements in nums[i...j]. If the product is less than k, increment the count.
i from 0 to n-1.j from i to n-1.prod = prod * nums[j].prod < k, count++.prod >= k, break inner loop (since elements are positive, product will only increase).Detailed Dry Run
| i | j | Prod | Result |
|---|---|---|---|
| 0 | 0 (10) | 10 | Count 1 |
| 0 | 1 (5) | 50 | Count 2 |
| 0 | 2 (2) | 100 | STOP |
| 1 | 1 (5) | 5 | Count 3 |
Intuition
We can transform the product comparison into a sum comparison using logarithms: . Since all elements are positive, the prefix sums of are monotonically increasing, allowing us to use Binary Search for each starting point.
prefixLogs where prefixLogs[i] is the sum of log(nums[0...i-1]).i, we need to find the largest j such that prefixLogs[j+1] - prefixLogs[i] < log(K) - epsilon (to handle floating point precision).j's for a fixed i is j - i + 1.Intuition
Standard variable-size sliding window. The key observation is that if a window [left, right] has a product < k, then ALL subarrays ending at right and starting between left and right also have products < k. There are right - left + 1 such subarrays.
Right - Left + 1 to result.nums[left] when product .Detailed Dry Run
| Right | Num | Product | Left | Count Add | Total |
|---|---|---|---|---|---|
| 0 | 10 | 10 | 0 | 1 | 1 |
| 1 | 5 | 50 | 0 | 2 | 3 |
| 2 | 2 | 100->10 | 1 | 2 | 5 |
| 3 | 6 | 60 | 1 | 3 | 8 |
⚠️ Common Pitfalls & Tips
Edge case k <= 1 is critical because the product of any subarray of positive integers is at least 1, which wouldn't be strictly less than 1.
Longest Turbulent Subarray
Find the maximum size of a 'turbulent' subarray where the comparison sign flips between adjacent pairs (e.g., a > b < c > d).
arr = [9, 4, 2, 10, 7, 8, 8, 1, 9]
[9 > 4] (Turbulent? Yes, Len 2)
[9 > 4 < 2] (Turbulent? No, 4 > 2 is same sign as 9 > 4)
[2 < 10 > 7 < 8] (Turbulent? Yes, Len 4)
[8 == 8] (Reset window)Examples
Intuition
Iterate through all possible starting points i. For each i, expand the subarray as long as it remains turbulent. Track the maximum length.
i from 0 to n-1.j starts from i.arr[j...j+1] satisfies the turbulent condition based on arr[j-1...j].i.Detailed Dry Run
| i | Turbulent Subarray | Length |
|---|---|---|
| 0 | [9, 4] | 2 |
| 1 | [4, 2] | 2 |
| 2 | [2, 10, 7, 8] | 4 |
| 6 | [8, 8] | 1 |
Intuition
We essentially track the 'alternating sign' property. If the comparison between arr[i-1] and arr[i] matches the alternating expectation, we expand. If they are equal, we reset. If they have the same sign as the previous pair, we slide the start to the previous element.
Integer.compare or sign functions.Detailed Dry Run
| i | Comparison | anchor | res |
|---|---|---|---|
| 1 | 9 > 4 (1) | 0 | 2 |
| 2 | 4 > 2 (1) | 1 | 2 |
| 3 | 2 < 10 (-1) | 2 | 2 |
| 4 | 10 > 7 (1) | 2 | 3 |
| 5 | 7 < 8 (-1) | 2 | 4 |
⚠️ Common Pitfalls & Tips
Equal elements (e.g., 8, 8) break the turbulence immediately and reset the anchor to the current index.
Replace the Substring for Balanced String
Find the minimum length of a substring that can be replaced to make all characters ('Q', 'W', 'E', 'R') appear exactly n/4 times.
s = "QQWE", n = 4, target = 1
Counts: Q:2, W:1, E:1, R:0
Over-limit: Q (2 > 1)
Goal: Find smallest window that contains the 'excess' characters.
Window [Q] (at index 0):
Remaining Counts outside window: Q:1, W:1, E:1, R:0
All remaining counts <= target? YES! (1, 1, 1, 0 <= 1)
Min Length = 1Examples
Intuition
Iterate through every possible substring that could be replaced. For each substring, calculate the character frequencies of the remaining part of the string. If all counts (Q, W, E, R) in the remaining part are , then the substring can be replaced to make the string balanced. Find the minimum length of such a substring.
i from 0 to n-1.j from i to n-1.s[0...i-1] and s[j+1...n-1].minLen = min(minLen, j - i + 1).Detailed Dry Run
| Substring [i, j] | Remaining Counts | Valid? |
|---|---|---|
| Global | Q:2, W:1, E:1, R:0 | NO |
| [0, 0] (Q) | Q:1, W:1, E:1, R:0 | YES! (Len 1) |
| [1, 1] (Q) | Q:1, W:1, E:1, R:0 | YES! (Len 1) |
Intuition
We can binary search for the minimum length L of the substring to replace. For a fixed length L, we check if any substring of size L can be replaced to make the entire string balanced. A string is balanced if all counts of 'Q', 'W', 'E', 'R' are exactly . Replacing a substring means the counts of remaining characters must be .
n/4.mid length:
mid across the string.mid is possible.mid.Intuition
A string is balanced if all counts are . To make a string balanced by replacing a substring, the characters outside that substring must all have counts . We search for the smallest window such that all characters remaining outside it satisfy this condition.
Detailed Dry Run
| Window | Count Q | Count W | Count E | Count R | Valid? |
|---|---|---|---|---|---|
| Global | 2 | 1 | 1 | 0 | NO |
| [Q] | 1 | 1 | 1 | 0 | YES |
| [QQ] | 0 | 1 | 1 | 0 | YES |
⚠️ Common Pitfalls & Tips
The goal is finding the smallest window that contains ALL excesses. If the string is already balanced, the answer is 0.
Get Equal Substrings Within Budget
Find the maximum length of a substring that can be transformed from s to t without exceeding maxCost.
s = "abcd", t = "bcdf", maxCost = 3
Costs: |a-b|=1, |b-c|=1, |c-d|=1, |d-f|=2
Window [abc] -> [bcd]: Cost = 1+1+1 = 3 (<= 3) Len 3
Window [bcd] -> [cdf]: Cost = 1+1+2 = 4 (> 3) XExamples
Intuition
Iterate through all possible substrings s[i...j]. For each substring, calculate the transformation cost by summing the absolute differences between s[k] and t[k] for all k in the range. If the cost , track the length.
i from 0 to n-1.j from i to n-1.currentCost = sum(abs(s[k] - t[k])) for k from i to j.currentCost <= maxCost, maxLen = max(maxLen, j - i + 1).Detailed Dry Run
| i | j | Substrings | Cost | Max Len |
|---|---|---|---|---|
| 0 | 0 | 'a'->'b' | 1 | 1 |
| 0 | 1 | 'ab'->'bc' | 1+1=2 | 2 |
| 0 | 2 | 'abc'->'bcd' | 1+1+1=3 | 3 |
| 0 | 3 | 'abcd'->'bcdf' | 3+2=5 | 3 |
Intuition
We can binary search for the maximum possible length L of a valid substring. For a fixed length L, we use a sliding window of size L to check if at least one window satisfies the maxCost constraint.
L is [0, n].mid):
mid across the strings.totalCost <= maxCost for any window, then mid is possible.Intuition
This is a standard variable-size sliding window problem on the array of transformation costs. We expand the window as long as the total cost is within the budget, and shrink from the left when it exceeds.
Right.Left as long as Sum > Budget.max(Result, Right - Left + 1).Detailed Dry Run
| Right | Cost | Total Cost | Left | Max Len |
|---|---|---|---|---|
| 0 | 1 | 1 | 0 | 1 |
| 1 | 1 | 2 | 0 | 2 |
| 2 | 1 | 3 | 0 | 3 |
| 3 | 2 | 5 -> 4 | 1 | 3 |
⚠️ Common Pitfalls & Tips
Be mindful of binary characters vs ASCII values. Use abs(ord(s[i]) - ord(t[i])) in Python or Math.abs(s.charCodeAt(i) - t.charCodeAt(i)) in JS.
Subarrays with K Different Integers
Count the number of 'good' subarrays where the number of different integers is exactly k.
nums = [1, 2, 1, 2, 3], k = 2
Exactly(K) = AtMost(K) - AtMost(K-1)
AtMost(2) Subarrays: [1], [2], [1,2], [1,2,1], [2,1,2] ...
AtMost(1) Subarrays: [1], [2], [1], [2], [3]
Exactly(2) = 12 - 5 = 7Examples
Intuition
Iterate through all possible substrings nums[i...j]. For each substring, count the number of unique integers. If the count is exactly k, increment the total result.
i from 0 to n-1.j from i to n-1.nums[i...j].set.size() == k, res++.set.size() > k, break inner loop (since distinct elements only increase).Detailed Dry Run
| i | j | Subarray | Distinct | Result |
|---|---|---|---|---|
| 0 | 0 | [1] | 1 | 0 |
| 0 | 1 | [1, 2] | 2 | 1 |
| 0 | 2 | [1, 2, 1] | 2 | 2 |
| 0 | 4 | [1, 2, 1, 2, 3] | 3 | STOP |
Intuition
We can use three pointers to find the number of subarrays with exactly k distinct integers directly. We maintain two 'left' pointers: left1 (minimum index to satisfy k distinct) and left2 (minimum index to satisfy k-1 distinct). The number of valid subarrays ending at right is left2 - left1.
count1 (frequencies for left1) and count2 (frequencies for left2).right, update both maps.left1 as far as possible such that the window [left1, right] has k distinct elements.left2 as far as possible such that the window [left2, right] has k-1 distinct elements.right, any start index in the range [left1, left2) produces a valid subarray.Intuition
Finding 'exactly K' is difficult with a single sliding window because shrinking doesn't always reduce the count of distinct elements. However, finding 'at most K' is a standard sliding window problem. Using the property Exactly(K) = AtMost(K) - AtMost(K-1) simplifies the problem significantly.
Exactly(K) = AtMost(K) - AtMost(K-1).Detailed Dry Run
| X | AtMost(X) |
|---|---|
| 2 | 12 |
| 1 | 5 |
| Result | 12 - 5 = 7 |
⚠️ Common Pitfalls & Tips
Be careful with the count map logic. Incrementing AtMost(K) means counting ALL subarrays with distinct elements.
Frequency of the Most Frequent Element
Maximize the frequency of an element by incrementing other elements by at most k overall.
nums = [1, 2, 4], k = 5
Sort: [1, 2, 4]
Window [1, 2, 4] ending at 4:
Cost to make all 4: (4-1) + (4-2) + (4-4) = 3 + 2 + 0 = 5
Cost 5 <= k (5)? YES! Frequency = 3Examples
Intuition
For each element x in the array, try to make a sequence of elements equal to x ending at x. Use a sliding window to find the maximum possible frequency for each starting position.
i from 0 to n-1.j from i to n-1.cost = sum(nums[j] - nums[k]) for k in [i...j].cost <= k, maxFreq = max(maxFreq, j - i + 1).Detailed Dry Run
| i | j | Window | Cost | Max Freq |
|---|---|---|---|---|
| 0 | 0 | [1] | 0 | 1 |
| 0 | 1 | [1, 2] | (2-1) = 1 | 2 |
| 0 | 2 | [1, 2, 4] | (4-1)+(4-2) = 5 | 3 |
Intuition
After sorting, we can binary search for the maximum frequency L. For a fixed L, we check if any subarray of length L exists such that the cost to make all elements equal to the largest element in that subarray is .
L is [1, n].mid length:
mid.[i, i + mid - 1] is nums[i + mid - 1] * mid - windowSum.cost <= k, mid is possible.Intuition
After sorting, for any window [left, right], it's always optimal to make all elements equal to the largest element nums[right]. The total cost is nums[right] * windowSize - windowSum. We maintain the largest possible window that satisfies cost <= k.
cost = lastVal * len - sum.Detailed Dry Run
| R | Num | Sum | Cost (4*Win - Sum) | Max Freq |
|---|---|---|---|---|
| 0 | 1 | 1 | 0 | 1 |
| 1 | 2 | 3 | 2*2 - 3 = 1 | 2 |
| 2 | 4 | 7 | 4*3 - 7 = 5 | 3 |
⚠️ Common Pitfalls & Tips
Integer overflow is a common issue here. nums[right] * (right - left + 1) can exceed 2^31 - 1, so use 64-bit integers (long in Java/C++, default in Python/JS) for intermediate calculations.
Longest Substring with At Most K Distinct Characters
Given a string s and an integer k, return the length of the longest substring that contains at most k distinct characters.
s = "eceba", k = 2
[e]
[e, c]
[e, c, e] (Distinct: 2 <= 2, Valid!)
[e, c, e, b] (Distinct: 3 > 2, INVALID!)Examples
Intuition
Check every possible substring and count unique characters. Update maximum length if the count is .
Intuition
Standard variable-size sliding window. Maintain a frequency map of characters in the window. When map size exceeds k, shrink from the left.
Count Complete Subarrays in an Array
A subarray is complete if the number of distinct elements in it is equal to the number of distinct elements in the entire array.
nums = [1, 3, 1, 2, 2], Total Distinct: 3
[1, 3, 1, 2] (Distinct: 3, VALID!)
[3, 1, 2] (Distinct: 3, VALID!)
[1, 2, 2] (Distinct: 2, INVALID)Examples
Intuition
Find the total number of distinct elements in the array first. Then, check every subarray and count how many are complete.
Intuition
This is equivalent to finding subarrays with at least k distinct elements. We can use the 'at least' pattern or the 'total - (at most k-1)' pattern.
Total Subarrays - Subarrays with at most (K-1) distinct elements.
Help us improve! Report bugs or suggest new features on our Telegram group.