力扣#395 至少有K个重复字符的最长子串(难度:中等)

题目:

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

解题思路:

假设长度t的一段区间满足要求的话,t+1长度的区间是否满足条件是不确定的,取决于t+1个位置出现的字符是否在原有区间内:

1. 如果新位置的字符在原有区间内,那必然还是满足出现次数大于K;

2. 如果新位置的字符在原有区间没出现过,那新字符的出现次数只有一次,那必然不满足要求;

因此我们无法使用二分法,相应的也无法直接使用【滑动窗口】+【双指针】。

在这里我们枚举最大长度所包含的字符类型数量,从1-26进行枚举,当确定了长度所包含的字符数量时,区间重新具有了二段性质。

当我们使用双指针的时候,

1. 右指针右移必然导致字符类型数量增加

2. 左指针右移必然导致字符类型数量减少

代码示例:

    public int longestSubstring(String s, int k) {
        int ants = 0;
        int n = s.length();
        char[] chars = s.toCharArray();
        int[] arr = new int[26];
        for (int p = 1; p <= 26; p++) {
            if (p > n) break;
            Arrays.fill(arr, 0);
            for (int i = 0, j = 0, tot = 0, sum = 0; i < n; i++) {
                int t = chars[i] - 'a';
                arr[t] ++;
                if (arr[t] == 1) tot++;
                if (arr[t] == k) sum++;
                while (tot > p) {
                    int u = chars[j++] - 'a';
                    arr[u]--;
                    if (arr[u] == 0) tot--;
                    if (arr[u] == k - 1) sum--;
                }
                if (tot == sum) ants = Math.max(ants, i - j + 1);
            }
        }
        return ants;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值