Documentation Index
Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt
Use this file to discover all available pages before exploring further.
Pattern Recognition Cheatsheet (Read This First)
What is Sliding Window?
The Sliding Window pattern maintains a dynamic “window” (a contiguous range) over a sequence, expanding and contracting it to find optimal subarrays or substrings. It reduces nested loops from O(n squared) to O(n) by reusing computations: instead of recalculating from scratch for every possible subarray, you update the window state incrementally — add the new element entering the window, remove the element leaving it. Think of it like looking through a physical window on a train. As the train moves forward, new scenery enters on one side and old scenery leaves on the other. You never need to go back and look at all the scenery from the start — you just update what you see as the window slides.Pattern Recognition Checklist
Use Sliding Window When
- Problem mentions contiguous elements
- Need subarray or substring
- Looking for maximum/minimum length
- Constraint on window (at most K, exactly K)
- Can solve by expanding and shrinking
Don't Use When
- Elements don’t need to be contiguous
- Need all subsets (use Backtracking)
- Sorted array hints (use Two Pointers)
- Need position of elements (use HashMap)
Canonical Template Code
Three templates cover 95% of sliding window problems. Memorize all three. The choice depends on whether the window size is fixed or variable, and (for variable) whether you are maximizing or minimizing the window.- Maximize valid window: shrink WHILE INVALID, update AFTER shrink loop.
- Minimize valid window: shrink WHILE VALID, update INSIDE shrink loop.
Three Types of Sliding Window
When to Use
Contiguous Subarrays
Substring Problems
Fixed Size Window
Variable Size Window
Pattern Variations
1. Fixed Size Window
The window size remains constant throughout. You initialize the window with the first k elements, then slide it one position at a time: add the element entering on the right, subtract the element leaving on the left. When to use: Problems that explicitly mention “window of size k,” “subarray of length k,” or “every group of k consecutive elements.” Complexity: O(n) time, O(1) space.2. Variable Size Window (Expand and Shrink)
The window grows (right pointer advances) until some condition is met, then shrinks (left pointer advances) to optimize the result. The expand-then-shrink dance is the heart of variable sliding window. Critical distinction: For “find the minimum valid window,” shrink while the window is valid (to minimize). For “find the maximum valid window,” shrink while the window is invalid (to restore validity), then the valid window before shrinking was a candidate. Complexity: O(n) time — each pointer moves at most n times. O(1) space for sum-based problems.3. Window with HashMap/Counter
Track element frequencies within the window.Classic Problems
1. Maximum Sum Subarray of Size K
1. Maximum Sum Subarray of Size K
2. Longest Substring Without Repeating Characters
2. Longest Substring Without Repeating Characters
3. Minimum Window Substring
3. Minimum Window Substring
4. Fruit Into Baskets
4. Fruit Into Baskets
5. Permutation in String
5. Permutation in String
Template Code
Sliding Window Decision Tree
Common Mistakes
Debugging Checklist
When your Sliding Window solution fails:Complexity Quick Reference
| Problem Type | Time | Space | Window Type |
|---|---|---|---|
| Max sum of K elements | O(n) | O(1) | Fixed |
| Longest substring no repeat | O(n) | O(min(n,m)) | Variable |
| Min window substring | O(n+m) | O(m) | Variable |
| Subarrays with K distinct | O(n) | O(K) | Variable |
| Max consecutive ones with K flips | O(n) | O(1) | Variable |
Interview Problems by Company
- Easy
- Medium
- Hard
| Problem | Company | Key Concept |
|---|---|---|
| Max Average Subarray I | Amazon | Fixed window basics |
| Contains Duplicate II | Meta | Fixed window + set |
| Max Consecutive Ones | Simple sliding | |
| Find All Anagrams | Amazon, Meta | Fixed window + frequency |
Interview Tips
How to Explain Your Approach
How to Explain Your Approach
- “I see this is about contiguous subarrays, so I’ll use Sliding Window.”
- “I’ll maintain a window with two pointers: left and right.”
- “Right pointer expands the window, left pointer shrinks it.”
- “I’ll track [state] to know when window is valid/invalid.”
- “This gives us O(n) time since each element is visited at most twice.”
When Interviewer Says...
When Interviewer Says...
| Interviewer Says | You Should Think |
|---|---|
| ”Find contiguous subarray” | Sliding Window! |
| ”Longest/shortest substring” | Sliding Window! |
| ”At most K distinct” | Variable window + shrink when > K |
| ”Exactly K” | AtMost(K) - AtMost(K-1) |
| “All subarrays of size K” | Fixed window |
| ”Contains permutation” | Fixed window + frequency match |
The AtMost Trick Explained
The AtMost Trick Explained
AtMost(K)counts all windows with 0, 1, 2, … K distinct elementsAtMost(K-1)counts all windows with 0, 1, 2, … K-1 distinct elements- Subtracting gives us ONLY windows with exactly K distinct elements
The “Exactly K” Trick
Practice Problems
| Problem | Difficulty | Link |
|---|---|---|
| Maximum Average Subarray I | Easy | LeetCode 643 |
| Longest Substring Without Repeating | Medium | LeetCode 3 |
| Minimum Window Substring | Hard | LeetCode 76 |
| Sliding Window Maximum | Hard | LeetCode 239 |
| Subarrays with K Different Integers | Hard | LeetCode 992 |
Practice Roadmap
Day 1: Fixed Window
- Solve: Max Average Subarray, Contains Duplicate II
- Focus: Understanding the slide (add new, remove old)
Day 2: Variable Window - Max
- Solve: Longest Substring Without Repeat, Longest Repeating Replacement
- Focus: Expand + shrink when invalid
Day 3: Variable Window - Min
- Solve: Minimum Size Subarray Sum, Minimum Window Substring
- Focus: Shrink while valid (opposite of max)
Memory Trick: SLIDE
Remember SLIDE for Sliding Window:- Subarray/Substring problem?
- Length constraints?
- Iterate with two pointers?
- Dynamic window size?
- Expand and shrink?
Worked LeetCode Problems
Five canonical problems. For each: signal, brute force first, optimized solution, common bugs.LC 3 — Longest Substring Without Repeating Characters
Problem. Given a string, find the length of the longest substring without repeating characters. Pattern fit. “Longest substring with [constraint]” -> variable sliding window, maximize. Brute force. For each starting index, scan forward checking duplicates. O(n squared) time, O(min(n, sigma)) space. Optimized.last_index[ch] >= left? Because the stored index might be from before the current window; ignoring stale indices would shrink the window incorrectly.
Complexity. O(n) time, O(min(n, sigma)) space (sigma is the alphabet size).
Common bugs.
- Forgetting the
>= leftguard. Causesleftto jump backward on stale indices, returning oversized windows. - Updating
last_index[ch]before checking it. Self-references the currentright, breaking the jump logic.
LC 76 — Minimum Window Substring
Problem. Given stringss and t, return the smallest substring of s that contains every character of t (with multiplicity). Return "" if none exists.
Pattern fit. “Smallest window containing all of T” -> variable window, MINIMIZE valid.
Brute force. All substrings, check each, O(n cubed).
Optimized.
have counter? Comparing two full Counters every step would be O(sigma) per step. Maintaining a single have integer that increments only when a character’s count exactly hits its requirement makes each expand/shrink step O(1).
Complexity. O(|s| + |t|) time, O(|s| + |t|) space.
Common bugs.
- Comparing full Counters every iteration. Gives O(n * sigma); times out on long strings.
- Decrementing
havewhen count drops below required. Use strict<not<=. If you use<=, you decrement on every removal of a character T does not need. - Forgetting to handle
tlonger thans. Should return"".
LC 209 — Minimum Size Subarray Sum
Problem. Given an array of positive integers and a target, return the minimal length of a contiguous subarray whose sum is greater than or equal to target. Return 0 if none. Pattern fit. “Shortest subarray with sum >= target”, positive integers -> variable window, MINIMIZE valid. Brute force. All subarrays O(n squared). Or prefix sum + binary search for O(n log n). Optimized (Sliding Window).- Using
ifinstead ofwhile. You only shrink once per iteration, missing smaller valid windows. - Updating best after the shrink loop. Then you miss the smallest window because
currentalready fell below target.
LC 340 — Longest Substring With At Most K Distinct Characters
Problem. Given a string, return the length of the longest substring that contains at most K distinct characters. Pattern fit. “Longest [substring] with at most K distinct” -> variable window, MAXIMIZE. Brute force. For each start, expand until distinct > K. O(n squared). Optimized.- Leaving zero-count keys in the dict.
len(count)then includes stale chars, shrinking too aggressively. - Hardcoding K=2 when interviewer asks for K=3. Always parameterize.
LC 567 — Permutation in String
Problem. Given stringss1 and s2, return true if s2 contains a permutation of s1.
Pattern fit. “Find anagram of fixed-length pattern in string” -> FIXED window of size |s1| + frequency match.
Brute force. Check every length-|s1| substring of s2 by sorting or hashing. O(n * m log m) with sort.
Optimized.
- Forgetting that
matchesshould track all 26 characters, not just chars in s1. Otherwise you miss the validity check. - Off-by-one in the window-removal step. Remove
s2[i - len(s1)]only afteri >= len(s1), not>.
Curated LeetCode Practice List
Easy (warm-up, 5-7 problems)
| LC # | Title | Variant tested |
|---|---|---|
| LC 643 | Maximum Average Subarray I | Fixed window basics |
| LC 1456 | Maximum Number of Vowels in Substring of Given Length | Fixed window character count |
| LC 219 | Contains Duplicate II | Fixed window with HashSet |
| LC 1004 | Max Consecutive Ones III | Variable window with K zeros (warm-up) |
| LC 121 | Best Time to Buy and Sell Stock | Single-pass with running min (sliding cousin) |
| LC 2090 | K Radius Subarray Averages | Fixed window with average |
Medium (the core, 7-9 problems)
| LC # | Title | Variant tested |
|---|---|---|
| LC 3 | Longest Substring Without Repeating Characters | Variable + HashMap |
| LC 209 | Minimum Size Subarray Sum | Variable + minimize, positive only |
| LC 567 | Permutation in String | Fixed window + frequency match |
| LC 438 | Find All Anagrams in a String | Fixed window + frequency match (multiple results) |
| LC 424 | Longest Repeating Character Replacement | Variable + most-frequent-char trick |
| LC 904 | Fruit Into Baskets | At most 2 distinct (LC 340 with K=2) |
| LC 159 | Longest Substring with At Most Two Distinct | At most K with K=2 |
| LC 1493 | Longest Subarray of 1s After Deleting One Element | Variable, at most one zero |
| LC 1248 | Count Number of Nice Subarrays | atMost(K) trick on odd numbers |
Hard (after Medium feels mechanical, 5-7 problems)
| LC # | Title | Variant tested |
|---|---|---|
| LC 76 | Minimum Window Substring | Variable minimize + frequency map + matches counter |
| LC 239 | Sliding Window Maximum | Fixed window + monotonic deque |
| LC 992 | Subarrays with K Different Integers | atMost(K) - atMost(K-1) |
| LC 862 | Shortest Subarray with Sum at Least K | Prefix sum + monotonic deque (negatives allowed) |
| LC 30 | Substring with Concatenation of All Words | Multiple fixed windows offset by word length |
| LC 1234 | Replace the Substring for Balanced String | Variable window with outside-window count |
| LC 1838 | Frequency of the Most Frequent Element | Sort + sliding window with K-replacement budget |
Interview Questions
Q1: You have an array of integers and a number K. Find the maximum sum of any contiguous subarray of size K. Walk me through your approach.
Q1: You have an array of integers and a number K. Find the maximum sum of any contiguous subarray of size K. Walk me through your approach.
- Recognize the pattern instantly. “Fixed size, contiguous subarray, optimization goal — this is textbook fixed sliding window.”
- Approach: Compute the sum of the first K elements. Then slide: add
arr[i], subtractarr[i - k]. Track the maximum seen. One pass, done. - Why it works: Instead of recomputing the sum from scratch for each window (O(n*k)), we reuse the previous sum and just adjust the two edges. Each element is added once and removed once.
- Edge cases to mention: Array shorter than K (return -1 or handle gracefully), K = 0, all negative numbers (the max sum is still the least negative window), integer overflow for large values.
- Complexity: O(n) time, O(1) space.
- What if I now ask for the maximum average of a subarray of size K? Does your approach change? (Answer: barely — divide the max sum by K at the end, no structural change.)
- What if the array contains negative numbers — does your sliding window still work? Why or why not? (Answer: yes, it works perfectly because we are looking at a fixed window size and just tracking sums. Negatives do not break the invariant.)
Q2: Given a string, find the length of the longest substring without repeating characters.
Q2: Given a string, find the length of the longest substring without repeating characters.
- Pattern recognition. “Substring plus longest plus a constraint on uniqueness — variable sliding window with a HashSet or HashMap.”
- Approach: Use two pointers
leftandright. Expandrightone character at a time. Ifs[right]is already in our set, shrink from the left until it is not. At each step, updatemax_length = max(max_length, right - left + 1). - HashMap optimization. Instead of shrinking one by one, store the last index of each character. When you hit a duplicate, jump
leftdirectly tomax(left, last_index[char] + 1). This avoids redundant shrink iterations. - Why
max(left, ...)? Because the stored index might be from before the current window’s left boundary. Without this check, you could accidentally move left backwards. - Complexity: O(n) time (each character visited at most twice with the set approach, exactly once with the jump approach), O(min(n, m)) space where m is the character set size (26 for lowercase, 128 for ASCII).
left could jump backwards. Saying space is O(n) without acknowledging the charset bound.Follow-ups:- What is the difference between using a HashSet with incremental shrinking versus a HashMap with index jumping? When does it matter? (Answer: both are O(n) amortized, but the HashMap approach has fewer operations in practice when there are long runs of unique characters followed by a repeat deep in the window.)
- If the input could be Unicode with millions of distinct code points, how does that affect your space analysis? (Answer: space becomes O(min(n, U)) where U is the Unicode range. In practice, you might use a HashMap instead of a fixed-size array to avoid allocating a huge array for a sparse charset.)
Q3: Find the minimum length subarray whose sum is greater than or equal to a given target. All elements are positive.
Q3: Find the minimum length subarray whose sum is greater than or equal to a given target. All elements are positive.
- Key insight. “For minimum-length problems, the shrink condition is inverted compared to maximum-length problems. I shrink while the window is valid to find the smallest valid window.”
- Approach: Expand
right, adding elements tocurrent_sum. Whenevercurrent_sum >= target, record the window length, then shrink from the left (subtractarr[left], incrementleft) and keep checking. This tries every possible left boundary for each right boundary. - Why
whilenotif? After removing one element from the left, the window might still be valid. We need to keep shrinking until it becomes invalid. - Why positive numbers matter. This approach relies on the monotonicity property: adding an element always increases the sum, removing always decreases it. With negative numbers, this invariant breaks and the sliding window approach fails entirely — you would need a different technique (like prefix sums + deque or Kadane’s variant).
- Complexity: O(n) time (each element added and removed at most once), O(1) space.
if instead of while for the shrink step. Not mentioning why positive elements are required. Updating the result after the shrink loop instead of during it.Follow-ups:- What happens if the array can contain negative numbers? Can you still use sliding window? (Answer: no. Negative numbers break the monotonicity.
current_sumcan decrease as you expand, so you cannot guarantee that shrinking improves the answer. You would need prefix sums with a deque or a binary search approach for O(n log n).) - What if I change the problem to “minimum length subarray with sum exactly equal to target”? Does your approach still work? (Answer: not directly. “Exactly equal” is harder because you cannot stop shrinking at “still valid.” You would need prefix sums + HashMap for O(n) on this variant.)
Q4: Given a string S and a string T, find the minimum window in S that contains all characters of T (including duplicates). This is LeetCode 76.
Q4: Given a string S and a string T, find the minimum window in S that contains all characters of T (including duplicates). This is LeetCode 76.
- High-level plan. “Build a frequency map of T. Use a variable window on S, expanding right to include characters, tracking how many characters of T are satisfied. Once all characters are covered, shrink from the left to minimize.”
- The
formedcounter trick. Instead of comparing two entire frequency maps on every step (which would be O(m) per step), maintain a single integerformedthat tracks how many unique characters from T are currently satisfied in the window. The window is valid whenformed == required(the number of unique characters in T). This keeps each expand/shrink step at O(1). - Shrink logic. When the window is valid, record it if it is the smallest seen, then remove
s[left]from the window frequency. If that character’s count drops below what T needs, decrementformed. Moveleftforward. - Edge cases: T longer than S (return empty), T has duplicate characters (frequency matters, not just presence), empty strings.
- Complexity: O(|S| + |T|) time, O(|S| + |T|) space in the worst case for the frequency maps. In practice O(1) extra space if the charset is fixed (e.g., 128 ASCII characters).
formed optimization and getting an O(26n) or worse solution.Follow-ups:- Walk me through how you handle duplicates. If T = “AABC”, and your window has one A, is it valid? (Answer: no. You need frequency-based tracking, not just presence. The window needs at least 2 A’s, 1 B, and 1 C.)
- Can you optimize this further for the case where |S| is very large but |T| is small? (Answer: yes, you can pre-filter S to only include positions where the character exists in T, creating a “filtered S” list. Then run sliding window on this smaller list. This helps when S has many irrelevant characters.)
Q5: Count the number of subarrays with exactly K distinct integers.
Q5: Count the number of subarrays with exactly K distinct integers.
atMost(K) - atMost(K-1) decomposition is non-obvious and separates candidates who have memorized templates from those who understand why the math works.Strong Answer:- Why direct counting fails. “With ‘at most K’, the window is monotonic: if a window has too many distinct elements, I shrink. But ‘exactly K’ is not monotonic — I might need to expand to get more distinct elements or shrink to remove some. The window does not have a clean valid/invalid boundary.”
- The decomposition.
exactly(K) = atMost(K) - atMost(K-1). The set of subarrays with at most K distinct includes those with 0, 1, 2, …, K distinct. Subtracting the set with at most K-1 distinct leaves only those with exactly K. - Counting subarrays in atMost. At each position of
right, the number of valid subarrays ending atrightisright - left + 1. This counts every subarray from[left, right]to[right, right]. - Why
right - left + 1? Each new rightmost element creates new subarrays: the subarray ending atrightstarting fromleft, fromleft+1, …, fromrightitself. That is exactlyright - left + 1new subarrays. - Complexity: O(n) time for each
atMostcall, O(n) total since we call it twice. O(K) space for the frequency map.
max_length instead of summing right - left + 1).Follow-ups:- Can you generalize this trick? Where else does the “exactly K = atMost(K) - atMost(K-1)” pattern apply? (Answer: it works for any problem where “at most K” has a monotonic window property but “exactly K” does not. Examples: count subarrays with exactly K zeros, count substrings with exactly K vowels.)
- What if I asked you to count subarrays with at least K distinct integers? (Answer:
atLeast(K) = total - atMost(K-1). Total subarrays =n*(n+1)/2. You only need oneatMostcall.)
Q6: Find the maximum of every contiguous subarray of size K (Sliding Window Maximum, LeetCode 239).
Q6: Find the maximum of every contiguous subarray of size K (Sliding Window Maximum, LeetCode 239).
- Why the basic approach fails. “A basic sliding window gives O(nk) because finding the max within each window is O(k). We need a way to track the max that supports add, remove, and query in O(1) amortized.”
- Monotonic deque approach. Maintain a deque that stores indices in decreasing order of their values. When adding
arr[right]: pop all indices from the back whose values are less than or equal toarr[right](they can never be the max for any future window). Then pushright. When the front of the deque is outside the window (index less than or equal toright - k), pop it from the front. The front always holds the current window max. - Why O(n) total. Each element is pushed onto the deque exactly once and popped at most once. Across all n elements, there are at most n pushes and n pops: O(n) total, O(1) amortized per operation.
- Alternative approaches. A balanced BST (like a TreeMap) gives O(n log k). A segment tree also works but is overkill. The deque is the optimal and expected solution.
- Complexity: O(n) time, O(k) space for the deque.
- What if I want the maximum of every subarray of variable size, not fixed K? How would you adapt this? (Answer: the deque approach generalizes. You just pop from the front when the index falls outside your current variable window’s left boundary instead of a fixed
right - k.) - Can you solve this problem in O(n) without a deque, using a different strategy? (Answer: yes, there is a block decomposition approach. Divide the array into blocks of size K, compute prefix max and suffix max within each block in O(n), then the max for any window spanning two blocks can be found in O(1). Total: O(n) time, O(n) space.)
Q7: Given an array of 0s and 1s, find the longest contiguous subarray of 1s if you can flip at most K zeros.
Q7: Given an array of 0s and 1s, find the longest contiguous subarray of 1s if you can flip at most K zeros.
- The reframing. “Flipping at most K zeros is equivalent to finding the longest window that contains at most K zeros. I do not need to actually track which zeros I flip.”
- Approach. Maintain a variable window. Expand
right. Ifarr[right] == 0, increment azero_count. Whenzero_count > K, shrink from the left: ifarr[left] == 0, decrementzero_count; moveleftforward. At each step,right - left + 1is a candidate answer. - Why this works. The window invariant is “at most K zeros inside.” As long as that holds, every element in the window could be a 1 (either it already is, or we “use” a flip on it). We want the longest such window.
- No HashMap needed. A single integer counter suffices because we are only tracking one thing (count of zeros). This gives O(1) space.
- Complexity: O(n) time, O(1) space.
- What if the problem changes to “at most K flips” but now the array has values 0, 1, 2 and you want the longest subarray of all-same values? Does sliding window still apply? (Answer: you would need to try each target value (0, 1, 2) separately and for each, find the longest window with at most K non-target elements. Still O(n) per target value, O(3n) = O(n) total.)
- What if the array is a stream and you do not know its length? Can you still use sliding window? (Answer: yes, sliding window naturally works on streams because it only needs the current element and the left boundary. You never need to look back beyond
left. You just need to store the window’s state, not the whole array.)
Q8: Given an array of positive and negative integers, find the subarray with the largest sum. Should you use sliding window?
Q8: Given an array of positive and negative integers, find the subarray with the largest sum. Should you use sliding window?
- The answer is no. “Sliding window does not work here because the array contains negative numbers, which breaks the monotonicity that sliding window depends on.”
- Why it breaks. Sliding window’s shrink step assumes that removing an element from the left makes the window “worse” (smaller sum) or “better” depending on a monotonic direction. With negatives, removing a negative element from the left increases the sum, and adding a negative element on the right decreases it. There is no consistent direction to shrink.
- What to use instead. Kadane’s algorithm: maintain
current_sumandmax_sum. At each element,current_sum = max(arr[i], current_sum + arr[i])— either extend the current subarray or start fresh. This is O(n) time, O(1) space, but it is not sliding window. It is a DP recurrence. - The general principle. Sliding window requires a monotonic condition: expanding always moves the window state in one direction, shrinking moves it in the other. When this breaks (negatives in sum problems, non-comparable elements), you need a different pattern.
- What if all elements are positive? Does sliding window apply to max subarray sum then? (Answer: if all elements are positive, the max sum subarray is the entire array. The problem becomes trivial — it is not that sliding window now works, it is that the problem is no longer interesting.)
- What if I modify the problem to “find the maximum sum subarray of length at most K”? Now can you use sliding window? (Answer: partially. You can use a sliding window of size K to find the max sum of exactly K, but “at most K” is trickier. A prefix sum + deque approach in O(n) is cleaner. The key insight is that this constraint bounds the window size, which partially restores the structure sliding window needs.)
Q9: You are given a string and need to find all starting indices of anagrams of a pattern P within it. How do you approach this?
Q9: You are given a string and need to find all starting indices of anagrams of a pattern P within it. How do you approach this?
- Pattern recognition. “Anagrams have the same character frequencies. Pattern P has a fixed length, so this is a fixed-size sliding window with frequency matching.”
- Approach. Build a frequency map for P. Maintain a window of size
len(P)over the string. As you slide, add the incoming character and remove the outgoing character. Instead of comparing full frequency maps each time (O(26) or O(m) per step), maintain amatchescounter: the number of characters whose frequency in the window exactly equals the frequency in P. Whenmatches == number of unique characters in P, you have found an anagram. - Updating matches in O(1). When adding a character: if its new count now equals P’s count, increment
matches. If it was equal before and now exceeds, decrementmatches. Symmetric logic for removal. This makes each slide step O(1). - Complexity: O(n) time where n is the length of the string (each slide is O(1)), O(1) space (at most 26 entries in the frequency maps for lowercase English letters).
- What if the pattern P is very long, say 100,000 characters? Does your approach still work efficiently? (Answer: yes. Building P’s frequency map is O(m), and the sliding step is still O(1) per position regardless of P’s length. Total is O(n + m), which is optimal.)
- How would you modify this if the problem asked for anagrams allowing at most K character substitutions? (Answer: this changes from exact match to approximate match. You would count mismatches instead of exact matches, and the window is valid when mismatches are at most K. Still fixed window, still O(n), but the counting logic changes.)
Q10: Given a string, find the length of the longest substring that contains at most 2 distinct characters. Now generalize to K.
Q10: Given a string, find the length of the longest substring that contains at most 2 distinct characters. Now generalize to K.
- Approach. “Variable sliding window with a HashMap tracking character frequencies. Expand right, adding characters. When the map has more than K keys (more than K distinct characters), shrink from the left until we are back to K or fewer.”
- Critical detail: deleting zero-count entries. When shrinking, decrement
freq[s[left]]. If it hits 0, you must delete the key from the map. If you leave zero-count entries,map.size()will overcount distinct characters and your window will shrink too aggressively. - Generalization. The code for K=2 and arbitrary K is identical — just parameterize the threshold. This is why interviewers start with K=2: they want to see if you hardcode or generalize.
- Real-world parallel. “This is like the ‘Fruit Into Baskets’ problem on LeetCode, which is just K=2 with a story wrapper.”
- Complexity: O(n) time (each character added and removed at most once), O(K) space for the frequency map.
- What is the difference between “at most K distinct” and “exactly K distinct”? How do you solve the “exactly” variant? (Answer: “exactly K” =
atMost(K) - atMost(K-1). You reuse the same function twice. This is the standard decomposition trick.) - What if the characters are not letters but arbitrary objects (like words in a stream)? Does your approach change? (Answer: structurally identical, but the HashMap key type changes. The time complexity stays O(n) and space becomes O(K) where K is the distinct-elements bound. The sliding window pattern is agnostic to what the elements are — it only cares about expand, shrink, and state tracking.)