仅含 1 的子串数
❤️ ❤️ 中等
题目介绍
给你一个二进制字符串 s(仅由 ‘0’ 和 ‘1’ 组成的字符串)。
返回所有字符都为 1 的子字符串的数目。
由于答案可能很大,请你将它对 10^9 + 7 取模后返回。
示例 1:
输入:s = “0110111”
输出:9
解释:共有 9 个子字符串仅由 ‘1’ 组成
“1” -> 5 次
“11” -> 3 次
“111” -> 1 次
示例 2:
输入:s = “101”
输出:2
解释:子字符串 “1” 在 s 中共出现 2 次
示例 3:
输入:s = “111111”
输出:21
解释:每个子字符串都仅由 ‘1’ 组成
示例 4:
输入:s = “000”
输出:0
提示:
- s[i] == ‘0’ 或 s[i] == ‘1’
- 1 <= s.length <= 10^5
分析及代码
- 先分析连续的1
例如: 1111
* 4个1
* 3个11
* 2个111
* 一个1111
* 一共4+3+2+1=(4+1)*4/2
- 总结:
对于n个连续的1,符合要求的有:(n+1)*n/2
对于不连续的1,可以把它当做几个连续的1的片段,再把片段加起来
- 代码1:
那么,直接遍历,用一个变量记录连续1的个数
如果遇到非零的数,则sum=sum+(n+1)*n/2
class Solution {
public:
int numSub(string s) {
int num=0,sum=0;
for(int i=0;i<s.size();i++){
if(s[i]=='1'){
num++;
}else{
sum = sum+(num+1)*num/2;
num=0;
}
}
return sum;
}
};
问题:
没有考虑到11011011的情况
- 代码2
class Solution {
public:
int numSub(string s) {
int num=0,sum=0;
for(int i=0;i<s.size();i++){
if(s[i]=='1'){
num++;
if(i+1==s.size()){
sum = sum+(num+1)*num/2;
}
}else{
sum = sum+(num+1)*num/2;
num=0;
}
}
return sum;
}
};
数组溢出问题
- 代码3
class Solution {
public:
int numSub(string s) {
long long num=0,sum=0;
for(int i=0;i<s.size();i++){
if(s[i]=='1'){
num++;
if(i+1==s.size()){
sum = sum+(num+1)*num/2;
}
}else{
sum = sum+(num+1)*num/2;
num=0;
}
}
return sum;
}
};
- 代码4:
class Solution {
public:
static constexpr int P = int(1E9) + 7;
int numSub(string s) {
int p = 0;
long long ans = 0;
while (p < s.size()) {
if (s[p] == '0') {
++p;
continue;
}
int cnt = 0;
while (p < s.size() && s[p] == '1') {
++cnt;
++p;
}
ans = ans + (1LL + (long long)cnt) * cnt / 2;
ans = ans % P;
}
return ans;
}
};