[刷题]Leetcode 395. 至少有K个重复字符的最长子串

同窗去面抖音被问到了这道题,赶忙去看了一下 发现本身也不会
哈哈哈哈哈,so.. 记个笔记 便于复习数组

题目描述code

找到给定字符串(由小写字符组成)中的最长子串 T , 
要求 T 中的每一字符出现次数都很多于 k 。
输出 T 的长度。

示例 1:字符串

输入:
s = "aaabb", k = 3
输出:
3
最长子串为 "aaa" ,其中 'a' 重复了 3 次。

示例 2:string

输入:
s = "ababbc", k = 2
输出:
5
最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次。

这道题的意思就是找一个子串,这个子串里的全部字符的出现频率都不低于K,找出最长的这样的子串
还有题目没有说太明确,其实由小写字符组成就是说只有‘a-z‘的小写字母,这样咱们就能够方便地用数组来统计啦~io

思路:
若是不知足条件的字符出如今了字符串两边好说,咱们只须要把两边不知足条件的字符去掉
麻烦的是 字符可能出如今中间 因而考虑用分治法去解决这个问题 把大问题划分为几个小问题, 若是字符出如今了中间 咱们就把字符串从这个字符这里劈开,左边去求解这个问题,右边也去求解这个问题,最后取左右俩边结果的最大值就OK了
关于某个字符是否知足条件,咱们只须要提早遍历一遍字符串,统计一下就OK了~class

代码以下:遍历

class Solution {
    public int longestSubstring(String s, int k) {
        if(s==null) return 0;
        if(s.length()==0) return 0;
        if(k<=1) return s.length();
        return count(s, k, 0, s.length()-1);
        

    }

    public int count(String s, int k, int left , int right){
        if(right-left+1<k) return 0;
        int[] cnt = new int[26];
        for(int i=left;i<=right;i++){
            ++cnt[s.charAt(i)-'a'];
        }
        // 去除左右两边不知足条件的字符
        while(right-left+1>=k && cnt[s.charAt(left)-'a']<k){
            left++;
        }

        while(right-left+1>=k && cnt[s.charAt(right)-'a']<k){
            right--;
        }
        if(right-left+1<k) return 0;
        
        // 劈开分治
        for(int i =left;i<=right;i++){
            // 只须要劈开一次就能够返回了,
            // 由于即便右边还有不知足条件的字符,
            // 也会在其子阶段求解获得了
            if(cnt[s.charAt(i)-'a']<k){
                return Math.max(count(s, k, left, i-1), count(s, k, i+1, right));
            }
        }
        return right-left+1;

    }

}
相关文章
相关标签/搜索