给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。
如果不存在这样的子字符串,则返回 0。
这题首先想到的就是滑动窗口,但是实际上手做起来感觉很棘手,因为你不知到什么时候该缩小窗口。
但是实际上还是有方法的。这题两种题解,一是递归分治,二是滑动窗口。先想想分治该怎么做:
法一:递归
设计递归:黑盒复用,知道输入输出值是什么
定义:longedtSubstr(s,k)
终止条件:s长度小于k,终止,返回0
调用递归,如果字符c不符合条件,那么就要所有不含c的字串,分割s->很多t,这样是不是缩小了规模?
未进入递归:所有字符都大于k,那么记录就完事了。
法二:滑动窗口
其实面对最关键的问题:什么时候缩小窗口。滑动窗口增加一个缩小的条件,那就是如果窗口里面字符的种类超过了count,就缩小窗口。
最后得到窗口里面,有count种字母,且每个字母都不小于k的长度。
其实我们可以反复测试符合多少个字符k的条件,
先测一个的,两个的.......从1~26,都for循环尝试一遍,取一个最大值,就是答案了。
26*n,时间复杂度还是O(n)。
递归题解:
"
class Solution {
public:
int longestSubstring(string s, int k) { return digui(s, k); }
void split(const string& s, vector
sv.clear();
istringstream iss(s);
string temp;
while (getline(iss, temp, flag)) {
sv.push_back(temp);
}
}
int digui(string tt, int k) {
if (tt.size() < k)
return 0; // 递归出口,不存在
vector<string> t;
unordered_map<char, int> map1;
for (char ch : tt) {
map1[ch]++;
}
for (auto& pair : map1) {
if (pair.second < k) {
split(tt, t, pair.first);
int ans = 0;
for (string tn : t) {
ans = max(ans, digui(tn, k));
}
return ans;
}
}
return tt.size();
}
};
"
浙公网安备 33010602011771号