[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 3171][备忘录][Go]关于LogTrick解法的个人理解](https://s3.inkorcloud.top/image/2025/10/3396d17ba0c1696cb78fb6e93d7d1d0b.png)
![[leetcode 3347][Go][答案二分]万能的二分法](https://s3.inkorcloud.top/image/2025/10/b92574e48ab8dfff1b32cc049a61df5f.png)
![[leetcode 3321][Go][有序集合]计算子数组的 x-sum II](https://s3.inkorcloud.top/image/2025/11/c9f55b2ecb04d16a57547b9f4de294ef.png)