题目描述
给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。
重复出现的子串要计算它们出现的次数。
示例 1 :
输入: “00110011”
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。
请注意,一些重复出现的子串要计算它们出现的次数。
另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。
示例 2 :
输入: “10101”
输出: 4
解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。
思路分析
- 我们可以把一个字符串分组,来记录数字出现了多少次。 比如 00111 我们可以分成groups=[2,3], 11110可以分成groups=[4,1]。当最后计数的时候,对每一个值取min(groups[i-1], groups[i]).。
这是为什么呢? 对于groups=[2,3]的情况,要么是00111要么是11000,无论是哪一种情况都可能的情况只有 0011 、01或是1100、10两个子串符合条件。也就是说,长度最小的那个决定了可能的子串情况。 - 根据上面的分析,用 j 遍历储存好了的groups列表,逐个比较最小的次数并且加到res 中去(这一点需要理解一下)假如groups=[2,3,2]的情况,第一个元素和第二个元素组合只可能是两种,第二个元素和第三个元素组合只可能是两种。
思路来源:https://blog.csdn.net/wenqiwenqi123/article/details/78462141
代码示例
class Solution(object):
def countBinarySubstrings(self, s):
"""
:type s: str
:rtype: int
"""
groups = [1]
for i in range(1,len(s)):
if s[i-1] != s[i]:
groups.append(1)
else:
groups[-1] += 1
res = 0
for j in range(1,len(groups)):
res += min(groups[j-1],groups[j])
return res