Given a string s and an integer k, return the length of the longest substring that contains at most k distinct characters.

Input: s = "eceba", k = 2
Output: 3
Explanation: The substring "ece" has 2 distinct characters and length 3.
Input: s = "aa", k = 1
Output: 2
Explanation: The substring "aa" has 1 distinct character and length 2.
Input: s = "aabbcc", k = 2
Output: 4
Explanation: The substrings "aabb" or "bbcc" have 2 distinct characters and length 4.
Constraints:

Contents

Sliding Window with Frequency Map

This is a classic dynamic sliding window problem. We expand the window by moving right forward and maintain a HashMap that counts the frequency of each character in the current window. When the number of distinct characters exceeds k, we shrink the window from the left until we are back to at most k distinct characters.

Implementation steps:
public int lengthOfLongestSubstringKDistinct(String s, int k) { if (k == 0 || s == null || s.isEmpty()) return 0; Map<Character, Integer> freq = new HashMap<>(); // char -> frequency in window int left = 0, maxLen = 0; for (int right = 0; right < s.length(); right++) { char c = s.charAt(right); freq.put(c, freq.getOrDefault(c, 0) + 1); // expand window // Shrink window until we have at most k distinct characters while (freq.size() > k) { char leftChar = s.charAt(left); freq.put(leftChar, freq.get(leftChar) - 1); if (freq.get(leftChar) == 0) { freq.remove(leftChar); // distinct count drops by 1 } left++; } maxLen = Math.max(maxLen, right - left + 1); } return maxLen; }
Trace through Example 1: s = "eceba", k = 2
rightcharmapleftwindowmaxLen
0e{e:1}0"e"1
1c{e:1,c:1}0"ec"2
2e{e:2,c:1}0"ece"3
3b{e:1,c:1,b:1} → shrink → {e:1,b:1}2"eb"3
4a{e:1,b:1,a:1} → shrink → {b:1,a:1}3"ba"3