395. 至少有 K 个重复字符的最长子串

一、题目

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

二、思路

分治思路:

  1. 对于当前String s,历遍并将所有字符进行出现次数记录
  2. 重新历遍String,如果发现其出现次数少于k,以当前i前后分别再调用longestSubstring(s.substring(0,i),k)以及longestSubstring(s.substring(i+1,s.length()),k)并取二者较大值
  3. 如果没有小于k的字符,直接返回当前string长度
  4. 完成分治之后直接返回

三、代码

class Solution {
    public int longestSubstring(String s, int k) {
        int n = s.length();
        return dfs(s, 0, n - 1, k);
    }

    public int dfs(String s, int l, int r, int k) {
        int[] cnt = new int[26];
        for (int i = l; i <= r; i++) {
            cnt[s.charAt(i) - 'a']++;
        }

        char split = 0;
        for (int i = 0; i < 26; i++) {
            if (cnt[i] > 0 && cnt[i] < k) {
                split = (char) (i + 'a');
                break;
            }
        }
        if (split == 0) {
            return r - l + 1;
        }

        int i = l;
        int ret = 0;
        while (i <= r) {
            while (i <= r && s.charAt(i) == split) {
                i++;
            }
            if (i > r) {
                break;
            }
            int start = i;
            while (i <= r && s.charAt(i) != split) {
                i++;
            }

            int length = dfs(s, start, i - 1, k);
            ret = Math.max(ret, length);
        }
        return ret;
    }
}

四、分析

复杂度分析

  • 时间复杂度:O(N⋅∣Σ∣),其中 N为字符串的长度,Σ 为字符集,本题中字符串仅包含小写字母,因此 ∣Σ∣=26|。由于每次递归调用都会完全去除某个字符,因此递归深度最多为 ∣Σ∣

  • 空间复杂度:O(∣Σ∣2)。递归的深度为 O(∣Σ∣),每层递归需要开辟 O(∣Σ∣)的额外空间。

 

posted @ 2023-02-23 21:44  ImreW  阅读(28)  评论(0)    收藏  举报