[leetcode 3234][Go]统计1显著的字符串的数量

[leetcode 3234][Go]统计1显著的字符串的数量
inkOrCloud题目链接
解题思路
设i为右边界,并记录每个0的坐标,pos0[0]为-1,pos0[n]为第n个0的坐标,每当i右移时进行以下操作:
记录0下标,记录1的数量
若s[i]为0,记录i并追加到pos0,设oneSum当前[0,i]内1的数量
1
2
3
4
5if s[i] == '1' {
oneSum++
} else {
pos0 = append(pos0, i)
}
计算以i结尾符合要求的子串数量
获取最近的0的坐标p,此时(p,i]内没有0,任意子串都符合要求,计算(p,i]内以i结尾的子串数量ret+=p-i
1
2
3//zeroSum表示[0,i]内0的数量
zeroSum := len(pos0)
ret += i - pos0[zeroSum-1]cnt0=zeroSum-j,计算(pos0[j-1],i]内1的数量cnt1=i-pos[j-1]-cnt0,若k为pos0[j-1]+1,不断右移k,此时每右移一次就会减少一个1,只要[k,i]之前1的数量大于0的数量的平方且k在j的左边,那么子串[k,i]符合条件
1
2
3
4
5
6
7
8
9
10
11//若[j,i]之间0的数量的平方已经大于[0,i]内1的数量便可结束遍历
for j := zeroSum - 1; j > 0 && (zeroSum-j)*(zeroSum-j) <= oneSum; j-- {
cnt0 := zeroSum - j
cnt1 := i - pos0[j-1] - cnt0
//k最多只能右移到j,所以cnt1-cnt0*cnt0+1应比pos0[j]-pos[j-1]小 for j := zeroSum - 1; j > 0 && (zeroSum-j)*(zeroSum-j) <= oneSum; j-- {
cnt0 := zeroSum - j
cnt1 := i - pos0[j-1] - cnt0
ret += max(0, min(pos0[j]-pos0[j-1], cnt1-cnt0*cnt0+1))
}
ret += max(0, min(pos0[j]-pos0[j-1], cnt1-cnt0*cnt0+1))
}
时间复杂度
外层循环为
完整代码
1 | func numberOfSubstrings(s string) int { |

![[leetcode 3321][Go][有序集合]计算子数组的 x-sum II](https://s3.inkorcloud.top/image/2025/11/c9f55b2ecb04d16a57547b9f4de294ef.png)
![[leetcode 2589][Go][贪心]完成所有任务的最少时间](https://s3.inkorcloud.top/image/2025/11/b966fd1a91aa1ea098b86e6d778523c2.png)
![[leetcode 1611][Go][位运算][记忆化搜索]使整数变为 0 的最少操作次数](https://s3.inkorcloud.top/image/2025/11/9715b5f3d8a7574ded3648767538558e.png)
![[leetcode 2528][Go][二分答案][差分数组][前缀和]最大化城市的最小电量](https://s3.inkorcloud.top/image/2025/11/fa0013722d9361b4383839722394dcf2.png)