解题思路
本题的目标是计算满足指定约束的子字符串数量。给定一个由字符 ‘0’ 和 ‘1’ 组成的字符串 s,要求所有子字符串中的 ‘0’ 或 ‘1’ 的数量最多为 k。为了解决此问题,我们可以采用滑动窗口的方法,对不同长度的子字符串进行统计。
-
初始统计:首先计算长度在 [n-k+1, n] 范围内的子字符串数量,直接加到结果 ans 中,因为这些长度较短的子字符串自动满足要求。
-
滑动窗口:对于长度 len 超过 k 的子字符串,统计窗口中 0 和 1 的数量。判断窗口中的字符数是否满足 0 或 1 的数量不超过 k,若满足则计入结果。然后利用滑动窗口,动态更新字符统计,继续判断窗口中的子字符串。
示例代码
class Solution {
public:
int countKConstraintSubstrings(string s, int k) {
int n = s.size();
int ans = 0;
// 计算长度在 [n-k+1, n] 的所有子字符串,直接计入结果
for(int i = n; i >= n - k + 1; i--)
ans += i;
// 遍历从长度 k+1 到 n 的子字符串
for(int len = k + 1; len <= n; len++) {
// 统计第一个窗口中 '0' 和 '1' 的数量
int num0 = 0;
int num1 = 0;
int i;
for(i = 0; i < len; i++) {
if(s[i] == '0') num0++;
else num1++;
}
// 若第一个窗口符合条件,结果计数 +1
if((num0 <= k) || (num1 <= k))
ans++;
// 滑动窗口遍历后续子字符串
for(i = len; i < n; i++) {
// 更新窗口中的 '0' 和 '1' 数量
if((s[i] == '0') && (s[i - len] == '1')) {
num0++;
num1--;
}
else if((s[i] == '1') && (s[i - len] == '0')) {
num1++;
num0--;
}
// 判断当前窗口是否符合条件
if((num0 <= k) || (num1 <= k))
ans++;
}
}
return ans; // 返回满足条件的子字符串数量
}
};