一、题目

1
2
3
4
5
6
7
8
9
10
Leetcode 3258题:

给你一个 二进制 字符串 s 和一个整数 k。

如果一个 二进制字符串 满足以下任一条件,
则认为该字符串满足 k 约束:
1. 字符串中 0 的数量最多为 k。
2. 字符串中 1 的数量最多为 k。
返回一个整数,表示 s 的所有满足 k 约束
的子字符串的数量。

二、输入

1
s 和 k

三、输出

1
2
返回一个整数,表示 s 的所有满足 k 约束 
的子字符串的数量。

四、示例

示例一

1
2
3
4
5
输入:
s = "10101", k = 1

输出:
12
  • 解释:s 的所有子字符串中,除了 “1010”、”10101” 和 “0101” 外,其余子字符串都满足 k 约束。

示例二

1
2
3
4
5
输入:
s = "1010101", k = 2

输出:
25

五、题解

  1. 这题是 LeetCode 简单题,实际做起来不简单
  2. 先理解题意子字符串是连续的,满足任一个最多 K 个字符的条件
  3. 一开始往排列组合集合方向想就复杂了
  4. 暴力方法是两重遍历,参考下面 Java 解法
  5. 优化的方法是滑动窗口,参考下面的 Python 解法。统计方法是针对每一个右边界位置,在满足题目条件时,累加符合条件的左边界字符个数,也就是 right - left + 1

5.1 Java 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public int countKConstraintSubstrings(String s, int k) {
int n = s.length();
int ans = 0;
for(int i = 0; i < n; i++) {
int[] cnt = new int[2];
cnt[0] = 0;
cnt[1] = 0;
for(int j = i; j < n; j++) {
cnt[s.charAt(j) - '0']++;

if(cnt[0] > k && cnt[1] > k) {
break;
}
++ans;
}
}

return ans;
}
}

5.2 Python实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution:
def countKConstraintSubstrings(self, s: str, k: int) -> int:
ans, left = 0, 0
cnt = [0, 0]
for right, c in enumerate(s):
cnt[int(c)] += 1
while cnt[0] > k and cnt[1] > k:
cnt[int(s[left])] -= 1
left += 1

# 以right为右边界返回子字符串的个数
ans += (right - left + 1)

return ans

obj = Solution()
ans = obj.countKConstraintSubstrings("10101", 1)
# 12
print(ans)
ans = obj.countKConstraintSubstrings("1010101", 2)
# 25
print(ans)
ans = obj.countKConstraintSubstrings("11111", 1)
# 15
print(ans)