Easy
题目描述
给定一个二进制字符串 s,返回具有相同数量的 0 和 1 的非空子串的数量,并且这些子串中的所有 0 和所有 1 都是连续分组的。
多次出现的子串要计算它们出现的次数。
示例 1:
输入:s = "00110011"
输出:6
解释:有 6 个子串具有相同数量的连续 1 和连续 0:"0011"、"01"、"1100"、"10"、"0011" 和 "01"。
请注意,一些重复出现的子串要计算它们出现的次数。
另外,"00110011" 不是有效的子串,因为所有的 0(和 1)没有组合在一起。
示例 2:
输入:s = "10101"
输出:4
解释:有 4 个子串:"10"、"01"、"10"、"01",具有相同数量的连续 1 和连续 0。
约束:
1 <= s.length <= 10^5s[i]要么是'0',要么是'1'
提示:
- 在 “000111” 中存在多少个有效的二进制子串,在 “11100” 中又有多少个?那么 “00011100” 呢?
解题思路
解题思路
这个问题的核心是找到满足条件的子串:有相同数量的0和1,且所有0和1都分别连续分组。
方法一:按组统计(推荐) 观察发现,符合条件的子串一定是由连续的0组和连续的1组组成,且这两个组的长度决定了能形成多少个有效子串。
算法步骤:
- 首先统计每个连续字符组的长度,存储在数组中
- 对于相邻的两个组,能形成的有效子串数量等于两组长度的最小值
- 例如"000111"有两组:长度3的0组和长度3的1组,可以形成min(3,3)=3个子串:“01”、“0011”、“000111”
方法二:双指针优化 我们可以进一步优化,不需要额外的数组存储所有组的长度,只需要记录前一组和当前组的长度即可。
这种方法的时间复杂度是O(n),空间复杂度是O(1),非常高效。
通过这种分组的思想,我们将复杂的子串匹配问题转换为简单的计数问题,大大简化了解决方案。
代码实现
class Solution {
public:
int countBinarySubstrings(string s) {
int result = 0;
int prevGroup = 0, currGroup = 1;
for (int i = 1; i < s.length(); i++) {
if (s[i] == s[i-1]) {
currGroup++;
} else {
result += min(prevGroup, currGroup);
prevGroup = currGroup;
currGroup = 1;
}
}
// 处理最后一对相邻组
result += min(prevGroup, currGroup);
return result;
}
};
class Solution:
def countBinarySubstrings(self, s: str) -> int:
result = 0
prev_group = 0
curr_group = 1
for i in range(1, len(s)):
if s[i] == s[i-1]:
curr_group += 1
else:
result += min(prev_group, curr_group)
prev_group = curr_group
curr_group = 1
# 处理最后一对相邻组
result += min(prev_group, curr_group)
return result
public class Solution {
public int CountBinarySubstrings(string s) {
int result = 0;
int prevGroup = 0, currGroup = 1;
for (int i = 1; i < s.Length; i++) {
if (s[i] == s[i-1]) {
currGroup++;
} else {
result += Math.Min(prevGroup, currGroup);
prevGroup = currGroup;
currGroup = 1;
}
}
// 处理最后一对相邻组
result += Math.Min(prevGroup, currGroup);
return result;
}
}
var countBinarySubstrings = function(s) {
let result = 0;
let prevGroup = 0, currGroup = 1;
for (let i = 1; i < s.length; i++) {
if (s[i]
复杂度分析
| 复杂度类型 | 大小 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 只需要遍历字符串一次 |
| 空间复杂度 | O(1) | 只使用了常数个额外变量 |