加载中...
返回

难题本 | LeetCode395. 至少有 K 个重复字符的最长子串

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

题目

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

示例1

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

  • 输出: 3

  • 解释: 最长子串为“aaa”,其中”a“重复了3次

示例2

  • 输入: s = “ababbc”, k = 2

  • 输出: 5

数据范围

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

分析

没有任何思路,参照题解的分治法将此题解出,稍作记录。

首先,对于 s 中的所有字符,我们可以统计它们出现的次数,对于所有出现次数小于 k 的字符,答案中一定不包含它。

则我们只需要考虑这些字符之外的子串。我们可以遍历整个字符串,当某个字符出现次数小于 k 的时候,将其位置记录下来;我们凭借这些位点,可以将原字符串 s 分割成许多个子串,然后按照相同的办法去处理这些子串即可。

按照这样的分析,整个题目可以使用递归的写法来实现分治算法。

AC代码

class Solution {
public:
    int longestSubstring(string s, int k) {
        if (s.size() < k)
            return 0;
        
        // 统计频数
        vector<int> cnt(26, 0);
        for (auto ch : s)
            cnt[ch - 'a']++;

        // 记录分割位点
        vector<int> split;
        for (int i = 0; i < s.size(); i++)
        {
            if (cnt[s[i] - 'a'] < k)
            {
                split.push_back(i);
            }
        }
        
        if (split.size() == 0)  // 无需分割
            return s.size();

        int start = 0;  // 当前子串的起点
        int res = 0;  // 最终答案
        for (auto pos : split)
        {
            // string.substr(pos, len)
            // 从位置pos开始的连续len个字符
            res = max(res, longestSubstring(s.substr(start, pos - start), k));
            start = pos + 1;
        }
        if (start != s.size() - 1)  // 对于最后一个子串
        {
            res = max(res, longestSubstring(s.substr(start, s.size() - start), k));
        }
        return res;
    }
};

参考资料

[1] 力扣官方题解.至少有K个重复字符的最长子串[EB/OL].2021-02-27

https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters/solution/zhi-shao-you-kge-zhong-fu-zi-fu-de-zui-c-o6ww/

[2] 负雪明烛.借本题帮助大家理解递归[EB/OL].2021-02-27

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/

[3] ffreturn.C++超100%的分治解法[EB/OL].2021-02-27

https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters/solution/cchao-100de-fen-zhi-jie-fa-by-ffreturn-uygu/

10 comments
Anonymous
Markdown is supported
@mpv945
mpv945commentedover 2 years ago

添加图片,如果使用外部图床的http链接 。图片无法点击放大,你那边怎么解决的?

@SGS4ever
SGS4evercommentedover 2 years ago

@mpv945
添加图片,如果使用外部图床的http链接 。图片无法点击放大,你那边怎么解决的?

我的博客没有使用图床,所以没办法帮到你~

@Celetherin
Celetherincommentedover 2 years ago

您好,我也是使用的stack主题,我在照着您的方法添加返回顶部按钮时,遇到了按钮虽然出现、也能够点击,但无法实现实际上的返回顶部功能的问题,我没有任何的代码知识,不知道您有没有解决方法?
另外,也是想提醒一下其他需要这篇教程的朋友,最新版的stack主题,添加返回按钮的组件应该在layouts/partials/sidebar/right.html, 在layouts/_default/single.html中添加代码会导致出现两个右边栏。

@jsjcjsjc
jsjcjsjccommentedover 2 years ago

请教一下博主,如何优雅的给stack主题添加广告哈?
我只想在左或者右侧边栏底部,或者每篇文章底部添加一个小小的广告,但是默认似乎的满屏广告哈~~
感谢

@SGS4ever
SGS4evercommentedover 2 years ago
@ClimbingMouse
ClimbingMousecommentedalmost 2 years ago

你好,按照你的方法设置页面载入动画,这个动画不会停止咋办啊

@46fafa
46fafacommentedalmost 2 years ago

博主你好,请问一下主页布局修改哪里的代码如何作用于整个网页,我发现修改后的布局只存在主页和前两篇文章,其他部分还是没修改的样子

@4kohakunushi
4kohakunushicommentedover 1 year ago

你好,关于左侧栏图标高亮我这里存在一些问题想请教你。我取消了原本主页直接抓取post的内容在中间显示的版块,这个部分改成了其他东西,与此同时新增了一个抓取post信息的与links、search等目录并列的一个目录,现在的问题是这些部分虽然都能正常显示,但是对应的抓取post的那个目录无法选中以后高亮,应该修改增加什么才能让它也可以选中后高亮呢?

@SGS4ever
SGS4evercommentedover 1 year ago

首先我只能基于本文使用的Stack版本来尝试解答,因为没看过当前的Stack主题的代码~
我重新翻了下此前写的关于高亮的内容,理论上只要你的post页面的标题在menu配置中即可高亮。如果post页面是你站点的根路径,那应该可以参考我的文章里写的方法,修改下active的触发逻辑~

@4kohakunushi
你好,关于左侧栏图标高亮我这里存在一些问题想请教你。我取消了原本主页直接抓取post的内容在中间显示的版块,这个部分改成了其他东西,与此同时新增了一个抓取post信息的与links、search等目录并列的一个目录,现在的问题是这些部分虽然都能正常显示,但是对应的抓取post的那个目录无法选中以后高亮,应该修改增加什么才能让它也可以选中后高亮呢?

@sansan-cc
sansan-cccommentedabout 2 months ago

感谢博主的建站帖子,有很大的帮助。

有朋自远方来,不亦说乎?