题目:
给你一个字符串 s
和一个整数 k
,请你找出 s
中的最长子串, 要求该子串中的每一字符出现次数都不少于 k
。返回这一子串的长度。
解题思路:
假设长度t的一段区间满足要求的话,t+1长度的区间是否满足条件是不确定的,取决于t+1个位置出现的字符是否在原有区间内:
1. 如果新位置的字符在原有区间内,那必然还是满足出现次数大于K;
2. 如果新位置的字符在原有区间没出现过,那新字符的出现次数只有一次,那必然不满足要求;
因此我们无法使用二分法,相应的也无法直接使用【滑动窗口】+【双指针】。
在这里我们枚举最大长度所包含的字符类型数量,从1-26进行枚举,当确定了长度所包含的字符数量时,区间重新具有了二段性质。
当我们使用双指针的时候,
1. 右指针右移必然导致字符类型数量增加
2. 左指针右移必然导致字符类型数量减少
代码示例:
public int longestSubstring(String s, int k) {
int ants = 0;
int n = s.length();
char[] chars = s.toCharArray();
int[] arr = new int[26];
for (int p = 1; p <= 26; p++) {
if (p > n) break;
Arrays.fill(arr, 0);
for (int i = 0, j = 0, tot = 0, sum = 0; i < n; i++) {
int t = chars[i] - 'a';
arr[t] ++;
if (arr[t] == 1) tot++;
if (arr[t] == k) sum++;
while (tot > p) {
int u = chars[j++] - 'a';
arr[u]--;
if (arr[u] == 0) tot--;
if (arr[u] == k - 1) sum--;
}
if (tot == sum) ants = Math.max(ants, i - j + 1);
}
}
return ants;
}