【LeetCode】395. 至少有K个重复字符的最长子串
作者:互联网
目录
题目链接:至少有K个重复字符的最长子串
题目描述
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
示例 1:
输入:
s = "aaabb", k = 3
输出:
3
最长子串为 "aaa" ,其中 'a' 重复了 3 次。
示例 2:
输入:
s = "ababbc", k = 2
输出:
5
最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次。
解题思路
这道题一开始以为不可以用滑窗,原因在于无法确定窗口左移、右移的条件。
后来看到题解的解法发现无法确定左右移的条件的原因是没有确定好窗口里的状态,即窗口里到底放什么。
解决办法:窗口里放不同种类的字符数,种类数最少为1,最多为26,也就是说做26次循环,每次循环窗口内的字符种类数i(i < 26)递增,这样就能得到所有可行的结果;
右移条件:不断的往前走,记录窗口内的字符种类数(diffCnt)和达到题目要求次数的字符数量(cnt);
左移条件:当窗口内字符种类数(diffCnt)超出了此次循环的限制时,缩小窗口减少字符种类数(diffCnt);
记录结果:当窗口内的字符种类(diffCnt)数满足循环要求且所有字符的出现次数(cnt)都达到题目要求是更新答案。
另外也可以使用分治的思想,把出现次数少于K次的字符作为分割符,对不同的子串分治求解。
实现代码
#include <bits/stdc++.h>
using namespace std;
int longestSubstring(string s, int k) {
int n = s.size();
//统计字符的数量
unordered_map<char, int> chCnt;
//限制滑窗里字符的数量
int res = 0;
for (int i = 0; i < 26; i++) {
chCnt.clear();
int left = 0, right = 0;
int diffCnt = 0, cnt = 0;
while (right < n) {
chCnt[s[right]]++;
if (chCnt[s[right]] == 1)
diffCnt++;
if (chCnt[s[right]] == k)
cnt++;
while (diffCnt > i) {
chCnt[s[left]]--;
if (chCnt[s[left]] == 0) {
diffCnt--;
}
if (chCnt[s[left]] == k - 1) {
cnt--;
}
left++;
}
//不同种类数为i个并且出现次数都至少K次
if (diffCnt == i && diffCnt == cnt) {
res = max(res, right - left + 1);
}
right++;
}
}
return res;
}
int main() {
string s = "ababbc";
int k = 2;
cout << longestSubstring(s, k);
return 0;
}
标签:子串,字符,cnt,right,diffCnt,int,395,chCnt,LeetCode 来源: https://blog.csdn.net/qq_31299203/article/details/114160267