问题描述
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
示例 1:
输入:
s = "aaabb", k = 3
输出:
3
最长子串为 “aaa” ,其中 ‘a’ 重复了 3 次。
示例 2:
输入:
s = "ababbc", k = 2
输出:
5
最长子串为 “ababb” ,其中 ‘a’ 重复了 2 次, ‘b’ 重复了 3 次。
解决思路
1、将所有的字母数目做一统计
2、有左右两个指针,如果对应的字母数量小于k,向内移动指针
3、找到左右两个指针中间数量小于k的字母,从此处分开,递归
4、结束条件:当剩余字符的数量小于k,返回0
代码实现
package solution;
class Solution {
public static void main(String[] args) {
Solution solution=new Solution();
int i=solution.longestSubstring("ababbc",2);
System.out.println(i);
}
public int longestSubstring(String s, int k) {
return part(s.toCharArray(),k,0,s.length()-1);
}
public int part(char[] arr,int k,int left,int right){
//所剩字母数量小于k,说明不满足条件
if(right-left+1<k){
return 0;
}
//记录字符数量的数组
int[] counts=new int[26];
//统计数量
for(int i=left;i<=right;i++){
counts[arr[i]-'a']=counts[arr[i]-'a']+1;
}
//向右移动指针
while (right-left+1>=k&&counts[arr[left]-'a']<k){
left++;
}
//向左移动指针
while (right-left+1>=k&&counts[arr[right]-'a']<k){
right--;
}
if(right-left+1<k){
return 0;
}
for (int i=left;i<=right;i++){
if(counts[arr[i]-'a']<k){
//如果中间还有不满足条件的字符,递归
return Math.max(part(arr,k,left,i-1),part(arr,k,i+1,right));
}
}
return right-left+1;
}
}