[LeetCode] Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子字符串

简介:

Find the length of the longest substring T of a given string (consists of lowercase letters only) such that every character in T appears no less than k times.

Example 1:

Input:
s = "aaabb", k = 3
Output:
3
The longest substring is "aaa", as 'a' is repeated 3 times.

Example 2:

Input:
s = "ababbc", k = 2
Output:
5
The longest substring is "ababb", as 'a' is repeated 2 times and 'b' is repeated 3 times.

这道题给了我们一个字符串s和一个正整数k,让我们求一个最大子字符串并且每个字符必须至少出现k次。作为LeetCode第三次编程比赛的压轴题目,博主再一次没有做出来,虽然难度标识只是Medium。后来在网上膜拜学习了大神们的解法,发现我当时的没做出来的原因主要是卡在了如何快速的判断某一个字符串是否所有的元素都已经满足了至少出现k次这个条件,虽然我也用哈希表建立了字符和其出现次数之间的映射,但是如果每一次都要遍历哈希表中的所有字符看其出现次数是否大于k,未免有些不高效。而用mask就很好的解决了这个问题,由于字母只有26个,而整型mask有32位,足够用了,每一位代表一个字母,如果为1,表示该字母不够k次,如果为0就表示已经出现了k次,这种思路真是太聪明了,隐约记得这种用法在之前的题目中也用过,但是博主并不能举一反三(沮丧脸:(),还得继续努力啊。我们遍历字符串,对于每一个字符,我们都将其视为起点,然后遍历到末尾,我们增加哈希表中字母的出现次数,如果其小于k,我们将mask的对应位改为1,如果大于等于k,将mask对应位改为0。然后看mask是否为0,是的话就更新res结果,然后把当前满足要求的子字符串的起始位置j保存到max_idx中,等内层循环结束后,将外层循环变量i赋值为max_idx+1,继续循环直至结束,参见代码如下:

解法一:

class Solution {
public:
    int longestSubstring(string s, int k) {
        int res = 0, i = 0, n = s.size();
        while (i + k <= n) {
            int m[26] = {0}, mask = 0, max_idx = i;
            for (int j = i; j < n; ++j) {
                int t = s[j] - 'a';
                ++m[t];
                if (m[t] < k) mask |= (1 << t);
                else mask &= (~(1 << t));
                if (mask == 0) {
                    res = max(res, j - i + 1);
                    max_idx = j;
                }
            }
            i = max_idx + 1;
        }
        return res;
    }
};

下面这种写法是上面的解法的递归写法,看起来简洁了不少,但是个人感觉比较难想,参见代码如下:

解法二:

class Solution {
public:
    int longestSubstring(string s, int k) {
        int n = s.size(), max_idx = 0, res = 0;
        int m[128] = {0};
        bool ok = true;
        for (char c : s) ++m[c];
        for (int i = 0; i < n; ++i) {
            if (m[s[i]] < k) {
                res = max(res, longestSubstring(s.substr(max_idx, i - max_idx), k));
                ok = false;
                max_idx = i + 1;
            }
        }
        return ok ? n : max(res, longestSubstring(s.substr(max_idx, n - max_idx), k));
    }
};

本文转自博客园Grandyang的博客,原文链接:至少有K个重复字符的最长子字符串[LeetCode] Longest Substring with At Least K Repeating Characters ,如需转载请自行联系原博主。

相关文章
|
15天前
|
算法
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
24 1
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
|
19天前
|
机器学习/深度学习 索引
【力扣】387. 字符串中的第一个唯一字符
【力扣】387. 字符串中的第一个唯一字符
|
2月前
|
存储
leetcode2744. 最大字符串配对数目
leetcode2744. 最大字符串配对数目
17 0
|
2月前
|
机器学习/深度学习 NoSQL Shell
力扣刷题-翻转字符串
力扣刷题-翻转字符串
12 1
|
2月前
|
机器学习/深度学习 算法
力扣刷题日常(一)
力扣刷题日常(一)
20 2
|
2月前
|
存储 索引
《LeetCode》—— LeetCode刷题日记
《LeetCode》—— LeetCode刷题日记
|
2月前
|
搜索推荐
《LeetCode》——LeetCode刷题日记3
《LeetCode》——LeetCode刷题日记3
|
2月前
|
容器
《LeetCode》——LeetCode刷题日记1
《LeetCode》——LeetCode刷题日记1
|
2月前
|
算法 测试技术
LeetCode刷题--- 430. 扁平化多级双向链表(深度优先搜索)
LeetCode刷题--- 430. 扁平化多级双向链表(深度优先搜索)

热门文章

最新文章