计数二进制子串

标签: 双指针 字符串

难度: Easy

给定一个字符串 s,统计并返回具有相同数量 01 的非空(连续)子字符串的数量,并且这些子字符串中的所有 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 <= 105
  • s[i]'0''1'

Submission

运行时间: 61 ms

内存: 16.4 MB

class Solution:
    def countBinarySubstrings(self, s: str) -> int:
        ret, n, cnt, c0= 0, 0, 0, s[0]
        for c1 in s:
            if c1 == c0:
                cnt +=1
            else:
                c0, n, cnt= c1, cnt, 1

            if cnt <= n:
                ret += 1
        return ret

Explain

该题解的思路是用两个变量cnt和n分别记录当前连续字符的个数和前一种连续字符的个数。遍历字符串,若当前字符与前一个字符相同,则cnt加1;否则,将前一种字符的个数n更新为cnt,cnt重置为1。每次更新n后,若cnt<=n,说明存在一个符合条件的子串,ret加1。最后返回ret即可。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def countBinarySubstrings(self, s: str) -> int:
        ret, n, cnt, c0= 0, 0, 0, s[0] # ret:返回值, n:前一个字符连续的个数, cnt:当前字符连续的个数, c0:前一个字符
        for c1 in s: # 遍历字符串
            if c1 == c0: # 若当前字符与前一个字符相同
                cnt +=1  # 当前字符连续个数加1
            else:
                c0, n, cnt= c1, cnt, 1 # 否则更新 c0为当前字符,n为前一个字符的连续个数cnt,cnt置为1

            if cnt <= n: # 若当前字符连续个数不超过前一个字符连续个数
                ret += 1 # 存在一个符合条件的子串,更新返回值
        return ret

Explore

在遇到不同字符时,我们需要切换统计对象,因为题目要求我们统计的是连续的0和1形成的子串,例如`01`或`10`。当字符从`0`变为`1`或从`1`变为`0`时,前一个字符的统计应该结束,开始新字符的统计。因此,我们需要记录前一个字符的连续个数`n`,以便与新字符的连续个数`cnt`进行比较,以判断是否形成了符合条件的子串。如果继续累加到`cnt`,则会混淆不同字符的界限,从而无法正确计算符合条件的二进制子串的数量。

是的,这个条件`cnt <= n`确实意味着只有当当前字符的连续长度小于或等于前一个字符的连续长度时,我们才认为找到了一个有效的子字符串。这是因为有效的子字符串需要由相等数量的`0`和`1`组成,例如`01`或`1100`。当当前字符的连续数小于或等于前一个字符的连续数时,我们可以确保从前一个字符的序列中取出足够数量的字符来与当前字符匹配,形成有效的子字符串。

算法初始化`c0`为`s[0]`,即字符串的第一个字符,这确保了无论字符串开始于`0`还是`1`,都能正确处理。初始化过程将自动适应第一个字符的类型,并开始计数。这种初始化方式不会对计数产生负面影响,而是确保从第一个字符开始即正确地统计连续的字符数。

如果字符串中所有字符都相同,例如`1111`或`0000`,那么算法将不会找到任何有效的二进制子字符串,因为不存在必要的字符变化(从`0`到`1`或从`1`到`0`)。在这种情况下,输出结果将是`0`。这是符合题目要求的,因为题目要求的是计数那些由相等数量的连续`0`和`1`组成的子字符串,而在全是相同字符的情况下,这样的子字符串不存在。