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

题目

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

示例 1:

输入:
s = “aaabb”, k = 3

输出:
3

最长子串为 “aaa” ,其中 ‘a’ 重复了 3 次。

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

思路

这个题目一开始我是用的滑动窗口的思路。
首先统计一下字符串中每个字符的个数,当滑动窗口的滑到一个字符的个数小于k的时候就缩小窗口,统计一下窗口内部满足条件的子串的长度。然后就有一些小小的问题,比如说str = “abbbaca”, k = 3。
当滑动窗口第一次停下来,进行内部元素统计的时候是 abbba , 这个时候,怎么缩小滑动窗口就有些困难。因为需要将l, r 同时进行一个调整。
我感觉滑动窗口的解决思路是首先获得一个[l, r]最大最小的可行解空间,然后增大l, 求一个最优解。但是,滑动到第二个a的时候,我无法得知abbb是一个最小的可行解,只有滑动到c的时候,我才知道abbbac是一个可行解,但不是最小的可行解,就造成了需要同时调整l, r。
所以就可以采用一个分治的思想,将原问题划分问一些子问题和另一些子问题,然后分别进行处理,因为无法很好的分成一个子问题和另一些子问题。
所以采用了递归分治的做法

代码

class Solution {
   
public:
    int longestSubstring(string s, int k) {
   
        if (k <= 1) return s.size();
        if (s.empty() || s.size() < k) return 0;
        
        vector<int> hash(128, 0);
        for (char c : s) ++hash[c];
        
        int i = 0;
        while (i < s.size() && hash[s[i]] >= k) ++i;
        if (i == s.size()) return s.size();

        int l = longestSubstring(s.substr(0, i), k);
        while (i < s.size() && hash[s[i]] < k) ++i;
        int r = longestSubstring(s.substr(i), k);
        
        return max(l, r);
    }
};

总结

滑动窗口应该是分治法的一个特例,
滑动窗口是将问题分成了一个子问题和另一些子问题
窗口内部就是一个子问题,然后在这个子问题内部求一个最优解

而这个题目,不太容易将问题划分为一个子问题和另一些子问题,
但是划分为一些子问题和另一些子问题比较容易,
所以就用一个递归的方法来解决。

全部评论

相关推荐

04-10 11:56
如皋中学 Java
高斯林的信徒:双c9能简历挂的?
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务