题目
Given a string, find the length of the longest substring T that contains at most k distinct characters.
For example, Given s = “eceba” and k = 2,
T is “ece” which its length is 3.
快慢指针 + HashMap
一般这种题目都是采用一个快慢 pointer来做
-
慢指针指向第一个起始位置 ,现在要决定的是什么时候更新慢指针pre
-
快指针指向当前的处理位置 i
当前的可能长度就是i - pre + 1的长度情况
思考为何要使用while 循环包裹在外面的情况
代码
public class longest {
public int solution(String s, int k){
if(s==null ||k<1)
return 0;
if(s.length()<k)
return s.length();
Map<Character, Integer> map =new HashMap<>();
int pre =0;
int result =k;
for(int i=0;i<s.length();i++){
//比如当前的处理元素是b, map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0)+1);
处理到当前合适位置的情况吧,情况 eceb 处理成为 eb 满足k=2;
while(map.size()>k){
char p =s.charAt(pre++);
int count = map.get(p);
count--;
if(count==0)
{
map.remove(p);
}
else
{
map.put(p,count);
}
}
result =Math.max(result,i-pre+1);
}
return result;
}
public static void main(String[] args) {
longest test =new longest();
System.out.println(test.solution("ececbac",2));
}
}
案例
在处理 ece 之前不用进行while(map.size()>k)这段代码的处理流程情况,
eceb 第一次while处理 后变成 ceb, 然后进入第二次处理流程的情况
eb 处理成为这样情况 最后 pre 变成了 2, 3-2+1 最大的长度为2 所以还是不满足该种情况
p
快慢指针
public class Solution {
public int lengthOfLongestSubstringKDistinct(String s, int k) {
if (s == null || s.length() == 0 || k <= 0) {
return 0;
}
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int count = 0;
int start = 0;
int max = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (map.containsKey(c)) {
map.put(c, map.get(c) + 1);
} else {
map.put(c, 1);
// 如果是第一次put的有可能
while (map.size() > k) {
char rm = s.charAt(start);
int tempCount = map.get(rm);
if (tempCount > 1) {
map.put(rm, tempCount - 1);
} else {
map.remove(rm);
}
start++;
//
count--;
}
}
count++;
max = Math.max(max, count);
}
return max;
}
}