【LeetCode-递归】至少有K个重复字符的最长子串

题目描述

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

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

题目链接: https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters/

思路

使用两个指针 left, right 表示在 [left, right] 范围内进行判断。首先统计 [left, right] 范围内字母的出现次数存入数组 cnt 中,然后根据字母出现的次数是否大于等于 k,从两边缩小范围。缩小范围后,判断新范围内是否有字符出现的次数小于 k,如果有,说明该字符不可能出现在结果当中,假设该字符的下标为 mid,则递归统计 [left, mid-1] 和 [mid+1, right] 范围内符合条件的长度,取较大者;否则,说明 [left, right] 范围内的字符出现次数均大于等于 k,返回范围的长度 right-left+1.

代码如下:

class Solution {
public:
    int longestSubstring(string s, int k) {
        if(s.empty() || s.size()<k) return 0;
        
        return count(s, k, 0, s.size()-1);
    }

    int count(string s, int k, int left, int right){
        if(right-left+1<k) return 0;

        vector<int> cnt(26, 0);
        for(int i=left; i<=right; i++) cnt[s[i]-'a']++;

        while(right-left+1>=k && cnt[s[left]-'a']<k) left++;
        while(right-left+1>=k && cnt[s[right]-'a']<k) right--;
        if(right-left+1<k) return 0;

        for(int mid = left; mid<=right; mid++){
            if(cnt[s[mid]-'a']<k){
                return max(count(s, k, left, mid-1), count(s, k, mid+1, right));
            }
        }
        return right-left+1;
    }
};

参考

https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters/

原文地址:https://www.cnblogs.com/flix/p/13332635.html