leetcode至少有K个字母的最长子串

 1. 至少有K个字母的最长子串

题目描述:给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。

算法思路:题目要求子串中每个字母的个数都要大于k,可以先统计字符串中每个字母出现的频率,如果存在某个字母a在整个字符串中出现的频率小于k,但是满足条件的子串绝对不可能包含字母a,因此可以用字母a将字符串分割成几个子串,对子串继续上述的判断方式,直到不存在这样的字母或者字符串长度为0。自此,我们将一个大问题分割成了几个小问题,可以使用递归的方式解决。递归的返回就是满足条件的子串长度,递归结束条件:字符串长度为0或者字符串中所有字母的出现频率都大于等于k。

    public int longestSubstring(String s, int k) {
        return longestSubstring(s, k, 0, s.length() - 1);
    }

    public int longestSubstring(String s, int k, int start, int end) {
        if (end - start + 1 < k) {
            return 0;
        }
        int[] total = new int[26];
        // 统计字符串中每个字母个数, 找出小于k个的字母
        for (int i = start; i <= end; i++) {
            total[s.charAt(i) - 'a']++;
        }
        int longestLen = 0;
        int left = start;
        for (int i = start; i <= end; i++) {
            // 字母在字符串中出现频率小于k, 需要切割子串, 继续递归判断
            if (total[s.charAt(i) - 'a'] < k) {
                longestLen = Math.max(longestLen, longestSubstring(s, k, left, i - 1));
                left = i + 1;
            }
        }
        // 字符串被切割过, 需要处理切割后的最后一段
        if(left != start) {
            return Math.max(longestLen, longestSubstring(s, k, left, end));
        }
        // 字符串没有被切割过, 满足至少k个重复字符条件
        return end - start + 1;
    }
原文地址:https://www.cnblogs.com/catpainter/p/14558131.html