340. 至多包含 K 个不同字符的最长子串
难度:中等
给定一个字符串 s ,找出 至多 包含 k 个不同字符的最长子串 T。
示例 1:
输入: s = "eceba", k = 2
输出: 3
解释: 则 T 为 "ece",所以长度为 3。
示例 2:
输入: s = "aa", k = 1
输出: 2
解释: 则 T 为 "aa",所以长度为 2。
解答:
class Solution {
//滑动窗口+哈希表
//时间复杂度O(N)。空间复杂度O(K)
//时间消耗在了查找最小值
public int lengthOfLongestSubstringKDistinct(String s, int k) {
int end = s.length();
if(end * k == 0) return 0;
int left = 0;
int right = 0;
int ansMax = 1;
Map<Character, Integer> map = new HashMap<>();
while(right < end){
map.put(s.charAt(right), right++);
if(map.size() == k + 1){
//核心代码
int del_index = Collections.min(map.values());
map.remove(s.charAt(del_index));
left = del_index + 1;
}
ansMax = Math.max(ansMax, right - left);
}
return ansMax;
}
}
class Solution {
//滑动窗口+有序字典
//时间复杂度O(N)。空间复杂度O(K)
public int lengthOfLongestSubstringKDistinct(String s, int k) {
int end = s.length();
if(end * k == 0) return 0;
int left = 0;
int right = 0;
int ansMax = 1;
LinkedHashMap<Character, Integer> map = new LinkedHashMap<>(k + 1);
while(right < end){
Character ch = s.charAt(right);
if(map.containsKey(ch)) map.remove(ch);
map.put(s.charAt(right), right++);
if(map.size() == k + 1){
//核心代码
Map.Entry<Character, Integer> leftMost = map.entrySet().iterator().next();
map.remove(leftMost.getKey());
left = leftMost.getValue() + 1;
}
ansMax = Math.max(ansMax, right - left);
}
return ansMax;
}
}
class Solution {
//滑动窗口+数组
//时间复杂度O(N)。空间复杂度O(128)
public int lengthOfLongestSubstringKDistinct(String s, int k) {
int[] arr = new int[128];
int cnt = 0, left = 0, right = 0, ans = 0;
while(right < s.length()) {
if (arr[s.charAt(right)] == 0) {
cnt++;
}
arr[s.charAt(right++)]++;
while(cnt > k) {
arr[s.charAt(left)]--;
if(arr[s.charAt(left)] == 0) {
cnt--;
}
left++;
}
ans = Math.max(ans, right - left);
}
return ans;
}
}
参考自:
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/longest-substring-with-at-most-k-distinct-characters/solution/zhi-shao-bao-han-k-ge-bu-tong-zi-fu-de-zui-chang-z/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。