题目
给你一个字符串s,请你返回满足以下条件且出现次数最大的任意子串的出现次数:
- 子串中不同字母的数目必须小于等于 maxLetters 。
- 子串的长度必须大于等于 minSize 且小于等于 maxSize 。
题解
class Solution {
/**
[minSize, maxSize] 表示子串窗口的大小
*/
public int maxFreq(String s, int maxLetters, int minSize, int maxSize) {
int res = 0;
for(int i = minSize; i <= maxSize; ++i) {
res = Math.max(res, getSubstrNum(s, i, maxLetters));
}
return res;
}
public int getSubstrNum(String s, int num, int maxLetters) {
int res = 0;
Map<String, Integer> map = new HashMap<>(); //键值为子串,实值为出现的次数
for(int i = 0; i <= s.length() - num; ++i) {
String str = s.substring(i, i + num);
//先判断是否满足不同字母数目要求
if(isOverLetter(str, maxLetters)) continue; //不满足,则获取下一个子串
//满足要求,则统计子串出现的次数,利用map保存
if(map.containsKey(str)) {
int cnt = map.get(str);
cnt++;
map.put(str, cnt);
}
else map.put(str, 1);
}
for(Map.Entry<String, Integer> entry : map.entrySet()) {
res = Math.max(res, entry.getValue());
}
return res;
}
// 判断子串中不同字母的数目是否满足要求
public boolean isOverLetter(String s, int maxLetters) {
int[] flag = new int[26];
for(int i = 0; i < 26; ++i) {
flag[i] = -1;
}
int res = 0;
for(int i = 0; i < s.length(); ++i) {
int idx = s.charAt(i) - 'a';
if(flag[idx] == -1) res++; //字符第一次出现,则+1
flag[idx]++;
}
if(res > maxLetters) return true;
return false;
}
}
憨憨解法,遍历了所有可能的子串长度,导致效率比较低
参考评论区:“abc” 肯定会覆盖 a, ab, 即长的肯定会覆盖短的,只要考虑最短的就好,对代码进行改进:
class Solution {
public int maxFreq(String s, int maxLetters, int minSize, int maxSize) {
int res = 0;
//for(int i = minSize; i <= maxSize; ++i) {
// res = Math.max(res, getSubstrNum(s, i, maxLetters));
//}
res = Math.max(res, getSubstrNum(s, minSize, maxLetters));
return res;
}
//...其他不变
}