LeetCode Entry
2537. Count the Number of Good Subarrays
Subarrays with at least k equal pairs window
2537. Count the Number of Good Subarrays medium
blog post
substack
youtube

Join me on Telegram
https://t.me/leetcode_daily_unstoppable/960
Problem TLDR
Subarrays with at least k equal pairs #medium #sliding_window #math
Intuition
Let’s observe sliding window:
// [3,1,4,3,2,2,4], k = 2
// freq
// i j 3->2
// i j 3->2 + 2->2 2
// i j 3->2 + 2->2 + 4->2 3
// i j 2->2 + 4->2 2
// i j 2->2 + 4->2 2
// when to move second pointer to shrink?
// ****************
// i j-> expand until good, + all before i count
// i-> j shrink while good
Expand window until we get k equal pairs.
The hardest part is to reason about when to shrink the window.
The count & shrink technique is: we always freeze the right border and shrink left while we can. The prefix is all valid subarrays, so count all of them.
Now, how to increase and decrease the frequency?
// freq = 4, (n - 1) * (n - 2) / 2
// freq = 5, n * (n - 1) / 2 - (n - 1) * (n - 2) / 2
// (n - n + 2) * (n - 1) / 2
// 2 * (n - 1) / 2
// n - 1
By looking at 1 1 1 1 1 example, the pairs count is p = f * (f - 1) / 2. So, the diff is p(n) - p(n - 1) = n - 1.
Approach
- we can shrink window up to the
invalidstate andnotcheck if it is valid to addj, asj = 0initially
Complexity
-
Time complexity: \(O(n)\)
-
Space complexity: \(O(n)\)
Code
fun countGood(n: IntArray, k: Int): Long {
val f = HashMap<Int, Int>(); var j = 0; var p = 0
return n.indices.sumOf { i ->
p += f[n[i]] ?: 0
f[n[i]] = 1 + (f[n[i]] ?: 0)
while (p >= k) { f[n[j]] = f[n[j]]!! - 1; p -= f[n[j++]]!! }
1L * j
}
}
pub fn count_good(n: Vec<i32>, mut k: i32) -> i64 {
let (mut f, mut j) = (HashMap::new(), 0);
(0..n.len()).map(|i| {
k -= f.get(&n[i]).unwrap_or(&0); *f.entry(n[i]).or_default() += 1;
while k <= 0 { *f.entry(n[j]).or_default() -= 1; k += f[&n[j]]; j += 1 }
j as i64
}).sum::<i64>()
}
long long countGood(vector<int>& n, int k) {
long long r = 0LL; unordered_map<int, int> f;
for (int i = 0, j = 0; i < size(n); ++i, r += j) {
k -= f[n[i]]++; while (k <= 0) k += --f[n[j++]];
} return r;
}