[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 ,如需转载请自行联系原博主。

相关文章
|
4天前
|
算法
力扣每日一题 6/23 字符串/模拟
力扣每日一题 6/23 字符串/模拟
5 1
|
4天前
|
索引
力扣每日一题 6/27 字符串 贪心
力扣每日一题 6/27 字符串 贪心
5 0
|
4天前
|
Python
力扣随机一题 模拟+字符串
力扣随机一题 模拟+字符串
5 0
|
4天前
力扣每日一题 6/22 字符串/贪心
力扣每日一题 6/22 字符串/贪心
4 0
|
4天前
力扣每日一题 6/18 字符串/模拟
力扣每日一题 6/18 字符串/模拟
4 0
|
18天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-2
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
18天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-1
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
19天前
|
索引
【LeetCode刷题】二分查找:山脉数组的峰顶索引、寻找峰值
【LeetCode刷题】二分查找:山脉数组的峰顶索引、寻找峰值
|
19天前
|
算法
【LeetCode刷题】滑动窗口解决问题:串联所有单词的子串(困难)、最小覆盖子串(困难)
【LeetCode刷题】滑动窗口解决问题:串联所有单词的子串(困难)、最小覆盖子串(困难)
|
19天前
|
算法 容器
【LeetCode刷题】滑动窗口解决问题:水果成篮、找到字符串中所有字母异位词
【LeetCode刷题】滑动窗口解决问题:水果成篮、找到字符串中所有字母异位词