可以使用 贪心 和 双指针 来解决这个问题。核心思想是统计相邻的 0 组和 1 组的大小,并计算能形成的平衡子字符串数量。
解题思路:
-
统计相邻相同字符的长度
-
遍历字符串
s
,计算相邻字符相同的连续子串长度,存入counts
数组。例如:s = "00110011" counts = [2, 2, 2, 2]
这里
[2, 2]
代表00
和11
,后面[2, 2]
代表00
和11
。
-
-
计算有效的子串数量
-
两个相邻的
counts[i]
和counts[i+1]
可以形成min(counts[i], counts[i+1])
个平衡子串。例如:-
00
和11
组合可以形成min(2,2) = 2
个01
或10
的子串。
-
-
代码实现:
def countBinarySubstrings(s: str) -> int:
counts = []
n = len(s)
i = 0
# 统计连续相同字符的长度
while i < n:
count = 1
while i + 1 < n and s[i] == s[i + 1]:
i += 1
count += 1
counts.append(count)
i += 1
# 计算相邻的 0 组和 1 组能形成的子字符串数量
ans = 0
for j in range(1, len(counts)):
ans += min(counts[j - 1], counts[j])
return ans
示例:
print(countBinarySubstrings("00110011")) # 输出: 6
print(countBinarySubstrings("10101")) # 输出: 4
复杂度分析:
-
时间复杂度: O(n),因为我们遍历了
s
两次(一次构造counts
,一次计算答案)。 -
空间复杂度: O(n),用于存储
counts
数组。
这种方法高效且容易理解,通过构造 counts
数组简化了问题。