前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode笔记:696. Count Binary Substrings

LeetCode笔记:696. Count Binary Substrings

作者头像
Cloudox
发布2021-11-23 16:40:05
3320
发布2021-11-23 16:40:05
举报
文章被收录于专栏:月亮与二进制月亮与二进制

问题(Easy):

Give a string s, count the number of non-empty (contiguous) substrings that have the same number of 0's and 1's, and all the 0's and all the 1's in these substrings are grouped consecutively. Substrings that occur multiple times are counted the number of times they occur. Example 1: Input: "00110011" Output: 6 Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01". Notice that some of these substrings repeat and are counted the number of times they occur. Also, "00110011" is not a valid substring because all the 0's (and 1's) are not grouped together. Example 2: Input: "10101" Output: 4 Explanation: There are 4 substrings: "10", "01", "10", "01" that have equal number of consecutive 1's and 0's. Note:

  • s.length will be between 1 and 50,000.
  • s will only consist of "0" or "1" characters.

大意:

给出一个字符串s,计算其有同样的0和1的非空(连续)子串的数量,且在该子串中所有的0和1都是连续的。 出现多次的子串要计算出现的次数。 例1: 输入:"00110011" 输出:6 解释:有6个子串有同样数量的连续的1和0:"0011", "01", "1100", "10", "0011", 和"01"。 注意其中有一些子串重复了,并且计算了发生的次数。 同时,"00110011"不是有效的子串,因为0(和1)没有排在一起。 例2: 输入:"10101" 输出:4 解释:有4个子串:"10", "01", "10", "01"有相等的连续的1和0。 注意:

  • s.length会在1到50000之间。
  • s只会由0和1字符组成。

思路:

通过一快一慢两个指针去遍历字符串,找到其中连续的0或者1,用一个flag来标记当前是连续的某个数字还是开始遇到另一种数字了。如果找到一样数目的了,就将结果数量加一。

有一个窍门是,当找到一个子串后,比如:“000111”,这是不要只把结果加一,而要加3,因为实际上它还包含了“0011”和“01”这两个符合要求的子串,所以有几个连续的数就加几,然后把慢的那个指针直接指到第一个不同的数字处,就不用一步步往前走这么慢以及重复计算了。

但是这种方案并没有通过,原因是在超长的字符串上运行超时了。

代码(C++):

代码语言:javascript
复制
class Solution {
public:
    int countBinarySubstrings(string s) {
        int res = 0;
        for (int i = 0; i < s.size(); i++) {
            int j = i+1;
            bool flag = true;
            int turenum = 1;
            int falsenum = 0;
            while (j < s.size()) {
                if (s[j] == s[i]) {
                    if (flag) turenum++;
                    if (!flag) break;
                } else if (s[j] != s[i]) {
                    if (flag) {
                        flag = false;
                        falsenum = 1;
                    } else {
                        falsenum++;
                    }
                    if (falsenum == turenum) {
                        res = res + turenum;
                        i = j - turenum;
                        break;
                    }
                }
                j++;
            }
        }
        return res;
    }
};

他山之石:

看了一个被人的方法,上面的窍门也利用到了,但是他并不是边遍历边计数,而是先遍历一遍字符串,记录每次重复的0和1的数量,比如:"00110011",遍历后记录为:“2222”。“00011”遍历后记录为:“32”。

然后再对这个新的记录,遍历,并取两个相邻数中较小的那一个,这实际上就是看每次响铃的0串和1串中会有的附和要求的子串数量了,速度快多了。

代码语言:javascript
复制
class Solution {
public:
    int countBinarySubstrings(string s) {
        vector<int> rec;
        int count = 1;
        for(int i=1, n=s.size(); i<=n; ++i){
            if(s[i] == s[i-1]){
                ++count;
            }else{
                rec.push_back(count);
                count = 1;
            }
        }
        int res = 0;
        for(int i=1, n=rec.size(); i<n; ++i){
            res += min(rec[i-1], rec[i]);
        }
        return res;
    }
};

合集:https://github.com/Cloudox/LeetCode-Record


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/1/26 上,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题(Easy):
  • 大意:
  • 思路:
  • 代码(C++):
  • 他山之石:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档