【双指针】LeetCode 340. 至多包含 K 个不同字符的最长子串
题目链接
给你一个字符串 s 和一个整数 k ,请你找出 至多 包含 k 个 不同 字符的最长子串,并返回该子串的长度。
示例 1:
输入:s = "eceba", k = 2
输出:3
解释:满足题目要求的子串是 "ece" ,长度为 3 。示例 2:
输入:s = "aa", k = 1
输出:2
解释:满足题目要求的子串是 "aa" ,长度为 2 。
思路
使用 HashMap
记录每种字符出现的次数,如果有字符出现次数从0变为1,则总字符数+1。如果总字符串超过了 \(k\),则向前移动左指针,直到小于等于 \(k\)。
代码
class Solution {
public int lengthOfLongestSubstringKDistinct(String s, int k) {
if(k == 0){
return 0;
}
HashMap<Character, Integer> hashMap = new HashMap<>();
char[] cs = s.toCharArray();
int result = 0;
// 总字符种类
int total = 0;
int left = 0;
int right = 0;
while(right < cs.length){
// 有新字符出现
if(hashMap.getOrDefault(cs[right], 0) == 0){
total++;
}
hashMap.put(cs[right], hashMap.getOrDefault(cs[right], 0) + 1);
// 总字符种类 > k
if(total > k){
// 因为扩张了之后才 > k,所以不计入新字符,也就不用 right - left + 1
result = Math.max(result, right - left);
while(left < right && total > k){
hashMap.put(cs[left], hashMap.get(cs[left]) - 1);
if(hashMap.get(cs[left]) == 0){
total--;
}
left++;
}
}
right++;
}
// 此时 right = cs.length,所以也不用 right - left + 1
result = Math.max(result, right - left);
return result;
}
}