Longest Substring with At Most K Distinct Characters
Expert Answer & Key Takeaways
A complete guide to understanding and implementing Two Pointers.
Longest Substring with At Most K Distinct Characters
Given a string
s and an integer k, return the length of the longest substring of s that contains at most k distinct characters.Visual Representation
s = "eceba", k = 2
Indices: 0 1 2 3 4
Chars: e c e b a
1. Window [0,0]: {e} (1 distinct) <= 2, Max=1
2. Window [0,1]: {e, c} (2 distinct) <= 2, Max=2
3. Window [0,2]: {e, c, e} (2 distinct) <= 2, Max=3
4. Window [0,3]: {e, c, e, b} (3 distinct) > 2
- Shrink from left: [1,3] -> {c, e, b} (3 distinct) > 2
- Shrink from left: [2,3] -> {e, b} (2 distinct) <= 2, Max=3Examples
Input: s = "eceba", k = 2
Output: 3
The substring is "ece" which has length 3.
Approach 1
Level I: Brute Force
Intuition
Generate all possible substrings and for each substring, count the number of distinct characters. If it's <= k, update the maximum length.
⏱ O(N^2)💾 O(K)
Detailed Dry Run
Input:
s = "eceba", k = 2i=0:j=0 (e): {e}, size=1 <= 2. maxLen = 1j=1 (c): {e, c}, size=2 <= 2. maxLen = 2j=2 (e): {e, c}, size=2 <= 2. maxLen = 3j=3 (b): {e, c, b}, size=3 > 2. BREAK
i=1:j=1 (c): {c}, size=1 <= 2. maxLen = 3j=2 (e): {c, e}, size=2 <= 2. maxLen = 3j=3 (b): {c, e, b}, size=3 > 2. BREAK
⚠️ Common Pitfalls & Tips
O(N^2) time complexity is too slow for N=10^5.
Approach 2
Level II: Sliding Window (Using Dictionary/Frequency Map)
Intuition
Instead of checking all substrings, use two pointers to maintain a window. Expand the right pointer, and if the count of unique characters exceeds
k, move the left pointer until the count is back to k.⏱ O(N)💾 O(K)
Detailed Dry Run
Input:
s = "eceba", k = 2r=0 (e): map={e:1}, size=1. max=1r=1 (c): map={e:1, c:1}, size=2. max=2r=2 (e): map={e:2, c:1}, size=2. max=3r=3 (b): map={e:2, c:1, b:1}, size=3 > 2.- Move
l=0 (e): map={e:1, c:1, b:1}, size=3 - Move
l=1 (c): map={e:1, b:1}, size=2. loop ends.
- Move
⚠️ Common Pitfalls & Tips
O(N) time but O(K) space for the mapping.
Approach 3
Level III: Optimal (Sliding Window + Hash Map)
Intuition
Use a sliding window with two pointers
i and j. Maintain a frequency map of characters in the current window. If the number of distinct characters exceeds k, shrink the window from the left until it's valid again.Add characters from the right. When
map.size() > k, remove from the left and update the count. Keep track of the max j - i + 1.⏱ O(N)💾 O(k)
Detailed Dry Run
eceba, k=2.
Window: [e,c,e] -> ok, max=3.
Add 'b': [e,c,e,b] -> distinct=3 > 2.
Shrink left until distinct <= 2: [e,b] -> ok, len=2.
⚠️ Common Pitfalls & Tips
Ensure the character count reaches zero before removing it from the map. Using a map size as the distinct count is robust.
Course4All Technical Board
Verified ExpertSenior Software Engineers & Algorithmic Experts
Our DSA content is authored and reviewed by engineers from top tech firms to ensure optimal time and space complexity analysis.
Pattern: 2026 Ready
Updated: Weekly
Found an issue or have a suggestion?
Help us improve! Report bugs or suggest new features on our Telegram group.