LeetCode 2067. 等计数子串的数量

2067. 等计数子串的数量

给你一个下标从 0 开始的字符串 s,只包含小写英文字母和一个整数 count。如果 s 的 子串 中的每种字母在子串中恰好出现 count 次,这个子串就被称为 等计数子串

返回 s 中 等计数子串 的个数。

子串 是字符串中连续的非空字符序列。

示例 1:

输入: s = "aaabcbbcc", count = 3
输出: 3
解释:
从下标 0 开始到下标 2 结束的子串是 "aaa"。
字母 “a” 在子串中恰好出现了 3 次。
从下标 3 开始到下标 8 结束的子串是 "bcbbcc"。
字母 “b” 和 “c” 在子串中恰好出现了 3 次。
从下标 0 开始到下标 8 结束的子串是 "aaabcbbcc"。
字母 “a”、“b” 和 “c” 在子串中恰好出现了 3 次。

示例 2:

输入: s = "abcd", count = 2
输出: 0
解释:
每种字母在 s 中出现的次数小于 count。
因此,s 中没有子串是等计数子串,返回 0。

示例 3:

输入: s = "a", count = 5
输出: 0
解释:
每种字母在 s 中出现的次数小于 count。
因此,s 中没有子串是等计数子串,返回 0。

提示:

  • 1 <= s.length <= 3 * 10^4
  • 1 <= count <= 3 * 10^4
  • s 只由小写英文字母组成。

提示 1

The brute force solution is to check every substring, which would TLE. How can we improve this solution?


提示 2

In an equal count substring, the first character appears count times, the second character appears count times, and so on.


提示 3

The length of an equal count substring is the number of unique characters multiplied by count.


提示 4

The length of all equal count substrings are multiples of count.

解法:滑动窗口

class Solution {
    public int equalCountSubstrings(String s, int count) {
        int n = s.length();
        if (n < count) {
            return 0;
        }
        int ans = 0;
        // 等计数子串的长度为count的整数倍,有多少不同的字母,其长度就是count的多少倍
        // 最多有26种字母,所以长度最多为count的26倍
        for (int i = 1; i * count <= n && i <= 26; i++) {
            int len = i * count;
            int left = 0;
            int right = 0;
            // 记录窗口内各种字母的数量
            int[] window = new int[26];
            // 记录窗口内 字母种类 的数量
            int valid = 0;
            while (right < n) {
                if (window[s.charAt(right) - 'a'] == 0) {
                    valid++;
                }
                window[s.charAt(right) - 'a']++;
                // 如果滑动窗口内的某个字母数量超过count,则此窗口已经不符合要求,左指针右移
                while (window[s.charAt(right) - 'a'] > count) {
                    window[s.charAt(left) - 'a']--;
                    if (window[s.charAt(left) - 'a'] == 0) {
                        valid--;
                    }
                    left++;
                }
                // 窗口长度为i * count时,检查其字母种类数是否为i
                if (right - left + 1 == len) {
                    if (valid == i) {
                        ans++;
                    }
                    window[s.charAt(left) - 'a']--;
                    if (window[s.charAt(left) - 'a'] == 0) {
                        valid--;
                    }
                    left++;
                }
                right++;
            }
        }
        return ans;
    }
}

复杂度分析

  • 时间复杂度:O(n),n 是 字符串 的长度,最坏情况下,时间复杂度为O(26n) = O(n) 。
  • 空间复杂度:O(1)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值