目录
统计二进制字符串中只含1的子字符串数目
题目描述
给定一个仅包含字符 '0'
和 '1'
的二进制字符串 s
,
求字符串中所有只由字符 '1'
组成的子字符串的数量。
由于答案可能非常大,最终结果需要对 109+710^9 + 7 取模后返回。
问题拆解
我们想知道字符串中包含的所有“只含 1
的子字符串”数量。例如:
- 对字符串
"111"
,所有只含1
的子串为:
"1"
,"1"
,"1"
,"11"
,"11"
,"111"
,共6个。 - 对字符串
"1011"
,只含1
的子串为:
"1"
(索引0),"1"
(索引2),"1"
(索引3),"11"
(索引2-3),共4个。
解题思路
核心思路是:
- 连续的
1
可以构成许多只包含1
的子串。
如果某段连续的 1
长度为 k
,那么这段连续 1
所包含的只由 1
组成的子串总数是:
这是因为:
- 长度为1的子串有
k
个(每个单独的1
)。 - 长度为2的子串有
k - 1
个。 - ...
- 长度为k的子串有 1 个。
将这些相加,就是等差数列求和公式。
解题方法
遍历字符串:
- 用一个变量
count
统计当前连续1
的长度。 - 每遇到一个
'1'
,count
加一,并将count
加到结果中(因为当前连续的1
会产生count
个新的只含1
的子串)。 - 遇到
'0'
,则将count
重置为 0。
此方法时间复杂度为 O(n),空间复杂度为 O(1),非常高效。
代码实现(Python)
class Solution:
def numSub(self, s: str) -> int:
MOD = 10**9 + 7
count = 0 # 当前连续1的长度
result = 0
for char in s:
if char == '1':
count += 1
result = (result + count) % MOD
else:
count = 0
return result
示例说明
举个具体例子说明:
s = "110111"
- 遍历到索引0,字符为
'1'
,count=1
,结果result=1
- 索引1,字符
'1'
,count=2
,结果result=1+2=3
- 索引2,字符
'0'
,count=0
,结果result=3
- 索引3,字符
'1'
,count=1
,结果result=3+1=4
- 索引4,字符
'1'
,count=2
,结果result=4+2=6
- 索引5,字符
'1'
,count=3
,结果result=6+3=9
最终结果是9,即:
只含1的子串包括:
"1"
(0),"1"
(1),"11"
(0-1)"1"
(3),"1"
(4),"1"
(5),"11"
(3-4),"11"
(4-5),"111"
(3-5)
复杂度分析与比较
方法 | 时间复杂度 | 空间复杂度 | 说明 |
直接枚举所有子串 | O(n^2) | O(1) | 超时,不适合大规模数据 |
连续1计数累加方法 | O(n) | O(1) | 高效且简洁,最优解 |
总结
本题核心是识别连续 1
的长度并利用等差数列求和公式高效计算子串数目。通过简单的线性扫描和计数,即可在 O(n) 时间内得到结果。
该方法简洁且避免了暴力枚举的超时问题,适合大规模字符串。