Description
Given a string, find the length of the longest substring T that contains at most k distinct characters.
Example 1:
Input: s = “eceba”, k = 2
Output: 3
Explanation: T is “ece” which its length is 3.
Example 2:
Input: s = “aa”, k = 1
Output: 2
Explanation: T is “aa” which its length is 2.
Solution
给一个String,找到只能有k个字符组成的最长的子序列的长度。
Approach 1: Sliding window. Maintain a sliding window with size k to get the max length. Using a int array to store the frequency of each character in s. Then j is the fast pointer in the right, I is the slow pointer in the left, count is the number of characters current used. If map do not contain this word, store its frequence and count++; If we have more than k words,
class Solution {
public int lengthOfLongestSubstringKDistinct(String s, int k) {
int[] map = new int[256];
int i = 0, count = 0, res = 0;
for (int j = 0; j < s.length(); j++){
if (map[s.charAt(j)]++ == 0){
count++;
}
while (count > k){
if (--map[s.charAt(i++)] == 0){
count--;
}
}
res = Math.max(res, j - i + 1);
}
return res;
}
}
more readable solution
public int lengthOfLongestSubstringKDistinct(String s, int k) {
int[] bits = new int[256];
int max = 0, index = 0;
int count = 0;
for(int i = 0; i < s.length(); i++) {
if(bits[s.charAt(i)] == 0) {
count++;
}
bits[s.charAt(i)]++;
while(count > k) { // count > k delete char from the substring
bits[s.charAt(index)]--;
if(bits[s.charAt(index)] == 0) {
count--;
}
index++;
}
max = Math.max(max, i - index + 1);
}
return max;
}
Time Complexity: O(n)
Space Complexity: O(256)
Approach 2: Using tree map to store the last occurance. But it is slower.
Code
class Solution {
public int lengthOfLongestSubstringKDistinct(String s, int k) {
if (s == null || s.isEmpty() || k == 0){
return 0;
}
//lastOccurance stores the last show of index i's character
TreeMap<Integer, Character> lastOccurance = new TreeMap<>();
//inWindow stores the char and the index of current window.
Map<Character, Integer> inWindow = new HashMap<>();
int i = 0;
int res = 1;
for (int j = 0; j < s.length(); j++){
char in = s.charAt(j);
//get new input char and if exceed window size, remove it.
while (inWindow.size() == k && !inWindow.containsKey(in)){
int first = lastOccurance.firstKey();
char out = lastOccurance.get(first);
inWindow.remove(out);
lastOccurance.remove(first);
i = first + 1;
}
//update or add new char in two maps.
if (inWindow.containsKey(in)){
lastOccurance.remove(inWindow.get(in));
}
inWindow.put(in, j);
lastOccurance.put(j, in);
res = Math.max(res, j - i + 1);
}
return res;
}
}
Time Complexity: O(nlogk)
Space Complexity: O(k)