Leetcode 395、至少有K个重复字符的最长子串

395、至少有K个重复字符的最长子串


前言

递归的思想还是比较容易理解的,代码写起来一如既往的那么艰难。


提示:以下是本篇文章正文内容,下面代码可供参考

一、题目の描述

找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
示例 1:
输入:
s = “aaabb”, k = 3
输出:
3
最长子串为 “aaa” ,其中 ‘a’ 重复了 3 次。
示例 2:
输入:
s = “ababbc”, k = 2
输出:
5
最长子串为 “ababb” ,其中 ‘a’ 重复了 2 次, ‘b’ 重复了 3 次。

二、使用步骤

递归+分治

  1. 对于字符串 s,如果存在某个字符ch,它的出现次数大于 0 且小于 k,则任何包含ch 的子串都不可能满足要求;
  2. .将字符串按照ch 切分成若干部分,则满足要求的最长子串一定出现在某个被切分的部分,而不能跨越一个或多个段;
  3. 考虑分治的方式求解本题。

代码如下(示例):

int dfs(char* s, int l, int r, int k) {
    int cnt[26];
    memset(cnt, 0, sizeof(cnt));
    for (int i = l; i <= r; i++) {
        cnt[s[i] - 'a']++;//由小写字母转换为数字进行表示
    }

    char split = 0;
    for (int i = 0; i < 26; i++) {
        if (cnt[i] > 0 && cnt[i] < k) {
            split = i + 'a';//标记不满足条件的字符
            break;
        }
    }
    if (split == 0) {
        return r - l + 1;//出现的字符均满足条件,返回数组长度
    }

    int i = l;//i代表当前字符串首位
    int ret = 0;
    while (i <= r) {
        while (i <= r && s[i] == split) {
            i++;//根据不满足条件的字符进行分割
        }
        if (i > r) {
            break;
        }
        int start = i;//start作为新的首位
        while (i <= r && s[i] != split) {
            i++;//寻找字符串末位
        }

        int length = dfs(s, start, i - 1, k);
        ret = fmax(ret, length);
    }
    return ret;
}

int longestSubstring(char* s, int k) {
    return dfs(s, 0, strlen(s) - 1, k);
}

三、总结

递归和分治的解法其实相对来说容易理解,只是我的代码功底实在是太差了,又是一点一点研究官方代码的一天,冲冲冲!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值