Count Substrings With K-Frequency Characters I
MediumUpdated: Aug 2, 2025
Practice on:
Problem
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.
Examples
Example 1
Input: s = "abacb", k = 2
Output: 4
Explanation:
The valid substrings are:
* `"aba"` (character `'a'` appears 2 times).
* `"abac"` (character `'a'` appears 2 times).
* `"abacb"` (character `'a'` appears 2 times).
* `"bacb"` (character `'b'` appears 2 times).
Example 2
Input: s = "abcde", k = 1
Output: 15
Explanation:
All substrings are valid because every character appears at least once.
Constraints
1 <= s.length <= 30001 <= k <= s.lengthsconsists only of lowercase English letters.
Solution
Method 1 – Sliding Window with Frequency Counting
Intuition
For each substring, we want to check if any character appears at least k times. Since the string is not too long (≤ 3000), we can use a sliding window approach: for every possible substring, count the frequency of each character and check if any count reaches k.
Approach
- For every possible starting index i, initialize a frequency array of size 26 (for lowercase letters).
- For every ending index j ≥ i, increment the count for s[j].
- If any character's count reaches k, mark the substring as valid and break (since we only need at least one such character).
- Count all such valid substrings.
- Return the total count.
Code
C++
class Solution {
public:
int countSubstrings(string s, int k) {
int n = s.size(), ans = 0;
for (int i = 0; i < n; ++i) {
vector<int> cnt(26, 0);
for (int j = i; j < n; ++j) {
cnt[s[j] - 'a']++;
if (*max_element(cnt.begin(), cnt.end()) >= k) {
ans++;
}
}
}
return ans;
}
};
Go
type Solution struct{}
func (Solution) CountSubstrings(s string, k int) int {
n := len(s)
ans := 0
for i := 0; i < n; i++ {
cnt := make([]int, 26)
for j := i; j < n; j++ {
cnt[s[j]-'a']++
for _, v := range cnt {
if v >= k {
ans++
break
}
}
}
}
return ans
}
Java
class Solution {
public int countSubstrings(String s, int k) {
int n = s.length(), ans = 0;
for (int i = 0; i < n; ++i) {
int[] cnt = new int[26];
for (int j = i; j < n; ++j) {
cnt[s.charAt(j) - 'a']++;
for (int v : cnt) {
if (v >= k) {
ans++;
break;
}
}
}
}
return ans;
}
}
Kotlin
class Solution {
fun countSubstrings(s: String, k: Int): Int {
val n = s.length
var ans = 0
for (i in 0 until n) {
val cnt = IntArray(26)
for (j in i until n) {
cnt[s[j] - 'a']++
if (cnt.any { it >= k }) {
ans++
}
}
}
return ans
}
}
Python
class Solution:
def countSubstrings(self, s: str, k: int) -> int:
n = len(s)
ans = 0
for i in range(n):
cnt = [0] * 26
for j in range(i, n):
cnt[ord(s[j]) - ord('a')] += 1
if max(cnt) >= k:
ans += 1
return ans
Rust
impl Solution {
pub fn count_substrings(s: String, k: i32) -> i32 {
let n = s.len();
let s = s.as_bytes();
let mut ans = 0;
for i in 0..n {
let mut cnt = vec![0; 26];
for j in i..n {
cnt[(s[j] - b'a') as usize] += 1;
if *cnt.iter().max().unwrap() >= k {
ans += 1;
}
}
}
ans
}
}
TypeScript
class Solution {
countSubstrings(s: string, k: number): number {
const n = s.length;
let ans = 0;
for (let i = 0; i < n; ++i) {
const cnt = Array(26).fill(0);
for (let j = i; j < n; ++j) {
cnt[s.charCodeAt(j) - 97]++;
if (Math.max(...cnt) >= k) {
ans++;
}
}
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(n^2 * 26), where n is the length of s, since we check all substrings and count frequencies. - 🧺 Space complexity:
O(26)for the frequency array.