LeetCode 395. 至少有K个重复的最长子串
题目描述
给你一个字符串 s
和一个整数 k
,请你找出 s
中的最长子串, 要求该子串中的每一字符出现次数都不少于 k
。返回这一子串的长度。
示例1:
输入:s = "aaabb", k = 3
输出:3
解释:最长子串为 "aaa" ,其中 'a' 重复了 3 次。
示例2:
输入:s = "ababbc", k = 2
输出:5
解释:最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次。
提示:
1 <= s.length <= 104
s
仅由小写英文字母组成1 <= k <= 105
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters
思路解析
直接采用暴力枚举的方法不可取,时间复杂度为 \(O(n^3)\),想办法降低时间复杂度。这里采用分治的方法来加速。
- 若某一字符
c
在s
中出现的次数小于k
次,那么可以确定最长的子串一定不包含c
,可以将s
在所有c
出现的地方进行分割,然后计算各个分割得到的子串中符合要求的最大子串。 - 若不存在这样的字符
c
,那么直接返回s
的长度即可。
代码实现
class Solution {
public:
int longestSubstring(string s, int k) {
if(s.empty()) return 0;
unordered_map<char, vector<int>> smap;
for(int i = 0; i < s.length(); i++) {
smap[s[i]].push_back(i);
}
for(auto p : smap) {
if(p.second.size() < k) {
int maxLen = longestSubstring(s.substr(0, p.second[0]), k);
for(int i = 0; i < p.second.size(); i++) {
int nextPos = (i == p.second.size() - 1) ? s.length() : p.second[i + 1];
string tmpStr = s.substr(p.second[i] + 1, nextPos - p.second[i] - 1);
int tmpLen = longestSubstring(tmpStr, k);
maxLen = max(maxLen, tmpLen);
}
return maxLen;
}
}
return s.length();
}
};