题目描述
给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。
链接:https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters
样例
示例 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
思路
分治。给定一个子串的范围,记录该子串中所有字符出现的次数。
然后找出出现次数没有达到k的字符,记录一个即可,记为sp。如果找不到,说明该子串满足定义,返回长度。
从左往右遍历当前子串不包含sp的小子串,递归。记录所有这些小子串的最大长度,最后返回。
代码
public class Solution {
public int longestSubstring(String s, int k) {
int right = s.length();
return Search(s, 0, right - 1, k);
}
int Search(String s,int left,int right,int k) {
int rcd[] = new int[26];
//记录所有字符出现次数
for(int i = left;i <= right;i++) {
rcd[s.charAt(i) - 'a'] += 1;
}
char sp = 'a';
int flg = -1;
//找出现过,但没有达到k的 字符,作为分割
for(int i = 0;i < 26;i++) {
if(rcd[i] > 0 && rcd[i] < k ) {
sp = (char) (sp + i);
flg = 1;
break;
}
}
//如果没找到,说明该子串满足条件
if(flg == -1) {
return right - left + 1;
}
int i = left;
int nowlen = 0;
while(i <= right) {
//找第一个不是sp的
while( i <= right && s.charAt(i) == sp) {
i++;
}
if(i > right)
break;
//找到了起点
int st = i;
while(i <= right && s.charAt(i) != sp) {
i++;
}
int lt = Search(s,st,i-1,k);
nowlen = Math.max(nowlen,lt);
}
return nowlen;
}
}