diff --git a/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/README.md b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/README.md new file mode 100644 index 0000000000000..7f7f63aa62f1f --- /dev/null +++ b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/README.md @@ -0,0 +1,180 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3329.Count%20Substrings%20With%20K-Frequency%20Characters%20II/README.md +tags: + - 滑动窗口 +--- + + + +# [3329. Count Substrings With K-Frequency Characters II 🔒](https://leetcode.cn/problems/count-substrings-with-k-frequency-characters-ii) + +[English Version](/solution/3300-3399/3329.Count%20Substrings%20With%20K-Frequency%20Characters%20II/README_EN.md) + +## 题目描述 + + + +

Given a string s and an integer k, return the total number of substrings of s where at least one character appears at least k times.

+ +

 

+

Example 1:

+ +
+

Input: s = "abacb", k = 2

+ +

Output: 4

+ +

Explanation:

+ +

The valid substrings are:

+ + +
+ +

Example 2:

+ +
+

Input: s = "abcde", k = 1

+ +

Output: 15

+ +

Explanation:

+ +

All substrings are valid because every character appears at least once.

+
+ +

 

+

Constraints:

+ + + + + +## 解法 + + + +### 方法一:滑动窗口 + +我们可以枚举子字符串的右端点,然后用一个滑动窗口维护子字符串的左端点,使得滑动窗口内的子字符串中的每个字符出现次数都小于 $k$。 + +我们可以用一个数组 $\textit{cnt}$ 维护滑动窗口内的每个字符的出现次数,然后用一个变量 $\textit{l}$ 维护滑动窗口的左端点,用一个变量 $\textit{ans}$ 维护答案。 + +当我们枚举右端点时,我们可以将右端点的字符加入滑动窗口,然后判断滑动窗口内右端点的字符出现次数是否大于等于 $k$,如果是,则将左端点的字符移出滑动窗口,直到滑动窗口内的每个字符出现次数都小于 $k$。此时,对于左端点为 $[0, ..l - 1]$,且右端点为 $r$ 的子字符串,都满足题目要求,因此答案加上 $l$。 + +枚举结束后,返回答案即可。 + +时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(|\Sigma|)$,其中 $\Sigma$ 是字符集,这里是小写字母集合,因此 $|\Sigma| = 26$。 + + + +#### Python3 + +```python +class Solution: + def numberOfSubstrings(self, s: str, k: int) -> int: + cnt = Counter() + ans = l = 0 + for c in s: + cnt[c] += 1 + while cnt[c] >= k: + cnt[s[l]] -= 1 + l += 1 + ans += l + return ans +``` + +#### Java + +```java +class Solution { + public long numberOfSubstrings(String s, int k) { + int[] cnt = new int[26]; + long ans = 0; + for (int l = 0, r = 0; r < s.length(); ++r) { + int c = s.charAt(r) - 'a'; + ++cnt[c]; + while (cnt[c] >= k) { + --cnt[s.charAt(l) - 'a']; + l++; + } + ans += l; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long numberOfSubstrings(string s, int k) { + int n = s.size(); + long long ans = 0, l = 0; + int cnt[26]{}; + for (char& c : s) { + ++cnt[c - 'a']; + while (cnt[c - 'a'] >= k) { + --cnt[s[l++] - 'a']; + } + ans += l; + } + return ans; + } +}; +``` + +#### Go + +```go +func numberOfSubstrings(s string, k int) (ans int64) { + l := 0 + cnt := [26]int{} + for _, c := range s { + cnt[c-'a']++ + for cnt[c-'a'] >= k { + cnt[s[l]-'a']-- + l++ + } + ans += int64(l) + } + return +} +``` + +#### TypeScript + +```ts +function numberOfSubstrings(s: string, k: number): number { + let [ans, l] = [0, 0]; + const cnt: number[] = Array(26).fill(0); + for (const c of s) { + const x = c.charCodeAt(0) - 97; + ++cnt[x]; + while (cnt[x] >= k) { + --cnt[s[l++].charCodeAt(0) - 97]; + } + ans += l; + } + return ans; +} +``` + + + + + + diff --git a/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/README_EN.md b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/README_EN.md new file mode 100644 index 0000000000000..3998822c4c34d --- /dev/null +++ b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/README_EN.md @@ -0,0 +1,180 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3329.Count%20Substrings%20With%20K-Frequency%20Characters%20II/README_EN.md +tags: + - Sliding Window +--- + + + +# [3329. Count Substrings With K-Frequency Characters II 🔒](https://leetcode.com/problems/count-substrings-with-k-frequency-characters-ii) + +[中文文档](/solution/3300-3399/3329.Count%20Substrings%20With%20K-Frequency%20Characters%20II/README.md) + +## Description + + + +

Given a string s and an integer k, return the total number of substrings of s where at least one character appears at least k times.

+ +

 

+

Example 1:

+ +
+

Input: s = "abacb", k = 2

+ +

Output: 4

+ +

Explanation:

+ +

The valid substrings are:

+ + +
+ +

Example 2:

+ +
+

Input: s = "abcde", k = 1

+ +

Output: 15

+ +

Explanation:

+ +

All substrings are valid because every character appears at least once.

+
+ +

 

+

Constraints:

+ + + + + +## Solutions + + + +### Solution 1: Sliding Window + +We can enumerate the right endpoint of the substring, and then use a sliding window to maintain the left endpoint of the substring, ensuring that the occurrence count of each character in the sliding window is less than $k$. + +We can use an array $\textit{cnt}$ to maintain the occurrence count of each character in the sliding window, then use a variable $\textit{l}$ to maintain the left endpoint of the sliding window, and use a variable $\textit{ans}$ to maintain the answer. + +When we enumerate the right endpoint, we can add the character at the right endpoint to the sliding window, then check if the occurrence count of the character at the right endpoint in the sliding window is greater than or equal to $k$. If it is, we remove the character at the left endpoint from the sliding window until the occurrence count of each character in the sliding window is less than $k$. At this point, for substrings with left endpoints in the range $[0, ..l - 1]$ and right endpoint $r$, all satisfy the problem's requirements, so we add $l$ to the answer. + +After enumeration, we return the answer. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(|\Sigma|)$, where $\Sigma$ is the character set, which in this case is the set of lowercase letters, so $|\Sigma| = 26$. + + + +#### Python3 + +```python +class Solution: + def numberOfSubstrings(self, s: str, k: int) -> int: + cnt = Counter() + ans = l = 0 + for c in s: + cnt[c] += 1 + while cnt[c] >= k: + cnt[s[l]] -= 1 + l += 1 + ans += l + return ans +``` + +#### Java + +```java +class Solution { + public long numberOfSubstrings(String s, int k) { + int[] cnt = new int[26]; + long ans = 0; + for (int l = 0, r = 0; r < s.length(); ++r) { + int c = s.charAt(r) - 'a'; + ++cnt[c]; + while (cnt[c] >= k) { + --cnt[s.charAt(l) - 'a']; + l++; + } + ans += l; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long numberOfSubstrings(string s, int k) { + int n = s.size(); + long long ans = 0, l = 0; + int cnt[26]{}; + for (char& c : s) { + ++cnt[c - 'a']; + while (cnt[c - 'a'] >= k) { + --cnt[s[l++] - 'a']; + } + ans += l; + } + return ans; + } +}; +``` + +#### Go + +```go +func numberOfSubstrings(s string, k int) (ans int64) { + l := 0 + cnt := [26]int{} + for _, c := range s { + cnt[c-'a']++ + for cnt[c-'a'] >= k { + cnt[s[l]-'a']-- + l++ + } + ans += int64(l) + } + return +} +``` + +#### TypeScript + +```ts +function numberOfSubstrings(s: string, k: number): number { + let [ans, l] = [0, 0]; + const cnt: number[] = Array(26).fill(0); + for (const c of s) { + const x = c.charCodeAt(0) - 97; + ++cnt[x]; + while (cnt[x] >= k) { + --cnt[s[l++].charCodeAt(0) - 97]; + } + ans += l; + } + return ans; +} +``` + + + + + + diff --git a/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.cpp b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.cpp new file mode 100644 index 0000000000000..7b3de87fd0cd5 --- /dev/null +++ b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.cpp @@ -0,0 +1,16 @@ +class Solution { +public: + long long numberOfSubstrings(string s, int k) { + int n = s.size(); + long long ans = 0, l = 0; + int cnt[26]{}; + for (char& c : s) { + ++cnt[c - 'a']; + while (cnt[c - 'a'] >= k) { + --cnt[s[l++] - 'a']; + } + ans += l; + } + return ans; + } +}; diff --git a/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.go b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.go new file mode 100644 index 0000000000000..b6197c5386a5a --- /dev/null +++ b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.go @@ -0,0 +1,13 @@ +func numberOfSubstrings(s string, k int) (ans int64) { + l := 0 + cnt := [26]int{} + for _, c := range s { + cnt[c-'a']++ + for cnt[c-'a'] >= k { + cnt[s[l]-'a']-- + l++ + } + ans += int64(l) + } + return +} diff --git a/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.java b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.java new file mode 100644 index 0000000000000..aa3278214ff2e --- /dev/null +++ b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.java @@ -0,0 +1,16 @@ +class Solution { + public long numberOfSubstrings(String s, int k) { + int[] cnt = new int[26]; + long ans = 0; + for (int l = 0, r = 0; r < s.length(); ++r) { + int c = s.charAt(r) - 'a'; + ++cnt[c]; + while (cnt[c] >= k) { + --cnt[s.charAt(l) - 'a']; + l++; + } + ans += l; + } + return ans; + } +} diff --git a/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.py b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.py new file mode 100644 index 0000000000000..75e15a81d3174 --- /dev/null +++ b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.py @@ -0,0 +1,11 @@ +class Solution: + def numberOfSubstrings(self, s: str, k: int) -> int: + cnt = Counter() + ans = l = 0 + for c in s: + cnt[c] += 1 + while cnt[c] >= k: + cnt[s[l]] -= 1 + l += 1 + ans += l + return ans diff --git a/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.ts b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.ts new file mode 100644 index 0000000000000..78ae9d491d26e --- /dev/null +++ b/solution/3300-3399/3329.Count Substrings With K-Frequency Characters II/Solution.ts @@ -0,0 +1,13 @@ +function numberOfSubstrings(s: string, k: number): number { + let [ans, l] = [0, 0]; + const cnt: number[] = Array(26).fill(0); + for (const c of s) { + const x = c.charCodeAt(0) - 97; + ++cnt[x]; + while (cnt[x] >= k) { + --cnt[s[l++].charCodeAt(0) - 97]; + } + ans += l; + } + return ans; +} diff --git a/solution/README.md b/solution/README.md index 18597644290bf..c2d319e9e99df 100644 --- a/solution/README.md +++ b/solution/README.md @@ -3339,6 +3339,7 @@ | 3326 | [使数组非递减的最少除法操作次数](/solution/3300-3399/3326.Minimum%20Division%20Operations%20to%20Make%20Array%20Non%20Decreasing/README.md) | `贪心`,`数组`,`数学`,`数论` | 中等 | 第 420 场周赛 | | 3327 | [判断 DFS 字符串是否是回文串](/solution/3300-3399/3327.Check%20if%20DFS%20Strings%20Are%20Palindromes/README.md) | `树`,`深度优先搜索`,`数组`,`哈希表`,`字符串`,`哈希函数` | 困难 | 第 420 场周赛 | | 3328 | [Find Cities in Each State II](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README.md) | `数据库` | 中等 | 🔒 | +| 3329 | [Count Substrings With K-Frequency Characters II](/solution/3300-3399/3329.Count%20Substrings%20With%20K-Frequency%20Characters%20II/README.md) | `滑动窗口` | 困难 | 🔒 | ## 版权 diff --git a/solution/README_EN.md b/solution/README_EN.md index 0da1915d93305..3ba349b9ba0d6 100644 --- a/solution/README_EN.md +++ b/solution/README_EN.md @@ -3337,6 +3337,7 @@ Press Control + F(or Command + F on | 3326 | [Minimum Division Operations to Make Array Non Decreasing](/solution/3300-3399/3326.Minimum%20Division%20Operations%20to%20Make%20Array%20Non%20Decreasing/README_EN.md) | `Greedy`,`Array`,`Math`,`Number Theory` | Medium | Weekly Contest 420 | | 3327 | [Check if DFS Strings Are Palindromes](/solution/3300-3399/3327.Check%20if%20DFS%20Strings%20Are%20Palindromes/README_EN.md) | `Tree`,`Depth-First Search`,`Array`,`Hash Table`,`String`,`Hash Function` | Hard | Weekly Contest 420 | | 3328 | [Find Cities in Each State II](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README_EN.md) | `Database` | Medium | 🔒 | +| 3329 | [Count Substrings With K-Frequency Characters II](/solution/3300-3399/3329.Count%20Substrings%20With%20K-Frequency%20Characters%20II/README_EN.md) | `Sliding Window` | Hard | 🔒 | ## Copyright