301-295- 至少有 K 个重复字符的最长子串-0105

在这里插入图片描述

题解

本题使用分治策略,如果某个字符的出现次数小于k,则用它将数组分开,再把每个子数组组委参数递归执行.如果都大于k,则将该字符串的长度返回.
用一个字符分割,往深了分割各子字符串,这个字符分割完成,使用另一个字符进行分割,而不是一次用多个字符进行分割.这个题递归有些绕

代码

 //301-295- 至少有 K 个重复字符的最长子串-0105
    int longestSubstringRes=0;
    public int longestSubstring(String s, int k) {
        if (s.length()<k){
            return 0;
        }
        // 统计个数
        HashMap<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            map.put(c,map.getOrDefault(c,0)+1);
        }
        // 分割
        for (Map.Entry<Character, Integer> entry : map.entrySet()) {
            if (entry.getValue()<k){
                for (String s1 : s.split(entry.getKey().toString())) {
                    // 对分割完成的子串进行递归
                    longestSubstringRes=Math.max(longestSubstringRes,longestSubstring(s1,k));
                }
                return longestSubstringRes;
            }
        }
        return s.length();

    }

法二 滑动窗口法

https://leetcode.cn/problems/longest-substring-with-at-least-k-repeating-characters/solution/xiang-jie-mei-ju-shuang-zhi-zhen-jie-fa-50ri1/
当窗口内满足条件的种类=窗口内字符的种类, 得到一个结果
窗口内的字符种类一定的情况下,求满足条件的子串

未到达p类–>判断–>达到p类–>判断–>p+1类–>left右移达到p类–>
当为p+1类时执行同样的步骤

滑动窗口逻辑上优点难度,看代码与注释

// 滑动窗口
public int longestSubstring(String s, int k) {
        int cnt[]=new int[26]; // 统计各字符个数
        int res=0;
        for (int p = 1; p <=26 ; p++) { // p代表窗口内字符的种类
             Arrays.fill(cnt, 0);
            int left=0,right=0,totalKind=0,matchKind=0;// totalKind 总种类  matchKind: 符合条件的种类
            while (right<s.length()){
                char c = s.charAt(right);
                int index=c-'a';
                cnt[index]++;
                if (cnt[index]==1){// 新加入一类
                    totalKind++;
                }
                if (cnt[index]==k){//如果满足条件
                    matchKind++;
                }

                // 如果总种类大于p,左指针右移,减小种类
                while (totalKind>p){
                    char c1 = s.charAt(left++);// 右移
                    int index1 = c1 - 'a';
                    cnt[index1]--;
                    if (cnt[index1]==0){// 去除该元素后少了一类
                        totalKind--;
                    }
                    if (cnt[index1]==k-1){// 满足条件的少了一类
                        matchKind--;
                    }

                }
                // 判断 当为p类时进行判断
                if (totalKind==matchKind){
                    res=Math.max(res,right-left+1);
                }
                 right++;
            }

        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

弈师亦友

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值