力扣刷题:395. 至少有 K 个重复字符的最长子串

题目:

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

示例 1:

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

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

提示:

1 <= s.length <= 104
s 仅由小写英文字母组成
1 <= k <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分治法:

这题可以通过分治法来求解。关键是把整个问题分成更小的子问题,并从子问题的解中得到答案。这里我们可以找到中间,并分为左右两边并找到结果。首先遍历s,如果遇到第一个无效值,也就是出现次数少于k的字母,标记它为中间值mid并向右遍历到下一个有效值validNext。从开始到中间值mid算作左边的子字符串,validnext到结束为右边的字符串。最后返回两者中结果最大的。如果一整个字符串都是有效,则直接返回结束到开始变量的差。

代码:

class Solution {
public:
    int longestSubstring(string s, int k) {
        int n = s.size();
        return helper(s,0,n,k);
    }
    
    int helper(string s, int start, int end, int freq)
    {
        if (end < freq)
        {
            return 0;
        }
        
        int count[26] = {0};
        // count all chars' frequency in substring
        for (int i = start; i < end; i++)
        {
            count[s[i]-'a']++;
        }
        
        for (int mid = start; mid < end; mid++)
        {
            // find first invalid char in the string
            if (count[s[mid]-'a'] >= freq)
            {
                continue;
            }
            int split = mid+1;
            // skip all invalid char
            while (split < end && count[s[split]-'a'] < freq)
            {
                split ++;
            }
            // compare left substring and right substring
            return max(helper(s, start, mid, freq), helper(s, split, end, freq));            
        }
        // if whole substring is valid, return its len
        return end-start;
    }
};

时间复杂度:最坏情况为O(n^2)

空间复杂度:o(n^2)

滑动窗口:

我们也可以用滑动窗口来解决这个问题。但是在这之前,注意一个条件:移动左右指针时,中间的字符类型数量会变化。这个数量很小,最大26个。我们可以利用这个条件去找出结果。通过计算不同字符类型数量的子数组的长度,我们就可以得出结果。

首先算出s里有多少个不同的字符,然后使用滑动窗口,计算每个不同字符类型数量的子数组里满足条件的子字符串的长度并更新最大值。

代码:

class Solution {
public:
    int longestSubstring(string s, int k) {
        int res=0;
        int maxUniques=getMaxUnique(s);
        int countMap[26];
        for (int curUnique = 1; curUnique <= maxUniques; curUnique++)
        {
            memset(countMap,0,sizeof(countMap));
            int start = 0;
            int end = 0;
            int curIndx = 0;
            int validCount = 0;
            int unique = 0;
            while (end < s.size())
            {
                if (unique <= curUnique)
                {
                    // expand sliding window
                    curIndx = s[end]-'a';
                    if (countMap[curIndx]==0)
                    {
                        unique += 1;
                    }
                    countMap[curIndx] ++;
                    if (countMap[curIndx] == k)
                    {
                        validCount ++;
                    }
                    end ++;
                }
                else
                {
                    // shrink sliding window
                    curIndx = s[start]-'a';
                    if (countMap[curIndx] == k)
                    {
                        validCount --;
                    }
                    countMap[curIndx] --;
                    if (countMap[curIndx] == 0)
                    {
                        unique--;
                    }
                    start ++;
                }
                if (unique == curUnique && unique == validCount)
                {
                    res = max(res, end - start);
                }
            }
        }
        return res;
    }
    
    
    int getMaxUnique(string s)
    {
        bool map[26] = {0};
        int res=0;
        for (char c:s)
        {
            if (!map[c-'a'])
            {
                res ++;
                map[c-'a'] = true;
            }
        }
        return res;
    }
};

参考:

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

https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters/solution/jie-ben-ti-bang-zhu-da-jia-li-jie-di-gui-obla/

https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters/solution/xiang-jie-mei-ju-shuang-zhi-zhen-jie-fa-50ri1/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值