LeetCode 696计数二进制子串

LeetCode 696计数二进制子串Easy

  • 题目简述:给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。重复出现的子串要计算它们出现的次数。

    s.length 在1到50,000之间。s 只包含“0”或“1”字符。

  • 题目本质: 统计二进制字符串中连续 1 和连续 0 数量相同的子字符串个数

  • 输入:“00110011” 输出:6 解释:有6个子串:01,10,01,0011,1100,0011它们具有相同数量的连续1和0。011001不是有效子串,因为所有的0和1没有连续

    输入:“10101” 输出:4 解释:有4个子串:10,01,10,01,它们具有相同数量的连续1和0。

  • 思路:中心扩展法,暴力遍历字符串,分别以01和10为中心向两侧扩展,适用于小数据,时间复杂度O(n2)

class Solution {
public:
    int cnt = 0; 
    void extendSubstrings(string s, int l, int r)
    {
        char sl = s[l];
        char sr = s[r];
        while(l >= 0 && r < s.size() && s[l] == sl && s[r] == sr)
        {
            l--;
            r++;
            cnt++;
        }
    }
    int countBinarySubstrings(string s) {
        for(int i = 1; i < s.size(); i++)
        {
            if(s[i - 1] == '0' && s[i] == '1')
            {
                extendSubstrings(s, i - 1, i);
            }
            if(s[i - 1] == '1' && s[i] == '0')
            {
                extendSubstrings(s, i - 1, i);
            }
        }
        return cnt;
    }
};
  • 思路二:满足要求的字符串不会存在0和1混合的情况,比如0101,1010

    例如:输入0011,那么输出为2

    1. 0,cur = 1, pre = 0,cnt = 0
    2. 0,cur = 2, pre = 0,cnt = 0
    3. 1,cur = 1, pre = 2,cnt = 1//答案为001中的01
    4. 1,cur = 2, pre = 2,cnt = 2//答案为0011中的0011
class Solution {
public:
    int countBinarySubstrings(string s) {
        int cnt = 0; // 满足要求的子串的个数
        int pre = 0; // 前一个字符出现的次数
        int cur = 1; // 当前的字符出现的次数
        for(int i = 1; i < s.size(); i++)
        {
            if(s[i] == s[i - 1]) 
                cur++;
            else 
            {
                pre = cur;//出现了不同的字符就更新前一个字符出现次数
                cur = 1;
            }
            // 前一个字符个数 >= 当前字符个数时,就找到一个答案
            if(pre >= cur) 
                cnt++;
        }
        return cnt;
    }
};

你可能感兴趣的:(LeetCode)