1.题目描述
给定一个字符串,求包含K个不同字符的最长字串的长度。
比如字符串"qeceba",K=3,那么最长子串为"qece",长度为4。
比如字符串"cvbnteeeeqeee",K=3,最长子串为'teeeeqeee",长度为9。
2.原题链接
LeetCode-340. 至多包含K个不同字符的最长子串【付费-Plus会员专享题】
3.解题思路
java
public static int longestSubstring(String str, int k) {
int longestSubstringLength = 0;
int substringStartIndex = -1;
Deque<Character> uniunCharDeque = new ArrayDeque<>();
Map<Character, Integer> charIndexMap = new HashMap<>();
char[] arr = str.toCharArray();
for (int i = 0; i < arr.length; i++) {
char c = arr[i];
//1.记录每个字符最新的位置:特别是针对重复的字符,需要更新其最新的位置,用来定位最新子串的起点。
charIndexMap.put(c, i);
//2.判断是否需要构建新的子串。
if (uniunCharDeque.contains(c)) {
//2.1不需要:当前队列已经有该字符,所以无需构建新的字串,但是需要刷新该字符在队列中的位置(通过删除再重新添加来实现刷新)。
uniunCharDeque.remove(c);
} else {
//2.2需要:当前子串中不包含当前字符,且队列中同步字符的数量已经达到阈值了,因此需要构建新的子串。
if (uniunCharDeque.size() >= k) {
//2.2.1 更新队列中的字符:由于将会新添加一个字符进来,因此需要移除队列中最早的字符。
Character first = uniunCharDeque.removeFirst();
//2.2.2 更新新子串的起点:新子串的起点就是队列中被移除的那个最早字符的最新位置。
substringStartIndex = charIndexMap.get(first);
}
}
//3.将当前字符放进队列。
uniunCharDeque.offer(c);
//4.刷新子串的最大长度:i表示当前位置,也就是当前子串的终点,start表示当前子串的起点。
longestSubstringLength = Math.max(longestSubstringLength, (i - substringStartIndex));
}
return longestSubstringLength;
}