Leetcode——696.计数二进制子串——三种题解+代码实现(擅于挖掘巧妙的题解思路)

一、题目


给定一个字符串 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到50,000之间。
  • s 只包含“0”或“1”字符。

二、题解思路


  •  题解思路1:多次遍历字符串,第一次遍历,看子字符串长度为2的情况,是否存在这样的子字符串;第二次遍历,看子字符串长度为4的情况.....;........,发现这样计算严重超时(不可取,说明有时候暴力破解是不行的)
  • 题解思路2:参考别人的想法,遍历字符串,将遍历过程中出现相同数字的个数存入数组,然后遍历数组,相邻两个值取最小的值,叠加求和即为满足要求的子串的个数、例如:1100100:数组中存的长度为2、2、1、2,相邻两个取最小:min(2,2)=2  (因为对于1100来说存在两种满足要求的连续子串:10、1100)、min(2,1)=1,min(1,2)=1.故满足要求的子串总和为2+1+1=4,输出为4。
  • 题解思路3:用last来记录之前一种字符的个数,cur来记录当前字符的个数,当last>=cur时,满足条件的子串计数变量自动加一。

三、代码实现


  •  C++代码实现题解思路1
class Solution {
public:
    int countBinarySubstrings(string s) 
    {
        int counts = 0;
        int size_1 = s.size();
        int counts1 = 2;
        while(counts1 <= size_1)
        {
            int i = 0;
            while(i+counts1-1<size_1)
            {
                string temp = s.substr(i,counts1);  //从i位置开始,截取counts1个字符
                int flag = 0;
                for(int j = 0;j<counts1/2;j++)
                {
                    if(temp[j] == temp[counts1-j])    //说明不是所有0和所有1都是组合在一起的
                        flag = 1;
                }
                if(flag == 0)    //是所有0和所有1组合在一起,flag标志位没变,则获得一个满足要求的子串
                    counts++;
                i++;       
            }
            counts1 = counts1 +2;
        }
        return counts;
    }
};
  • C++代码实现题解思路2
class Solution {
public:
    int countBinarySubstrings(string s) 
    {
        vector<int> nums;
        int counts = 1;
        for(int i =0;i<s.size()-1;i++)   //将0或1连出现的次数依次记下来
        {
            if(s[i] == s[i+1])
            {
                counts++;
                if(i+1 == s.size()-1 && s[i+1] == s[i])  //最后一个字符和倒数第二个字符一样
                    nums.push_back(counts);
            }
            else
            {
                nums.push_back(counts);
                counts = 1;
            }
        }
        if(counts == 1)    //如果最后一个字符不是和倒数第二个一样,则需要往数组中再存入一个1
            nums.push_back(1);
        int count_sum = 0;
        for(int i = 0;i<nums.size()-1;i++)
        {
            count_sum += min(nums[i],nums[i+1]);   //取相邻两个字符的最小值叠加入总和
        }
        return count_sum;
    }
};
  • C++代码实现题解思路3
class Solution {
public:
    int countBinarySubstrings(string s) 
    {
        int last = 0;  //前一种字符的个数变量
        int cur = 1;   //当前字符的个数变量
        int count = 0;  //满足要求的子串个数
        for(int i = 1;i<s.size();i++)   //对于s长度为1的情况,直接不满足,然后直接不执行for循环
        {
            if(s[i]==s[i-1])    //当前的字符与前一个字符一样
            {
                cur++;  //当前字符个数加1
            }
            else
            {
                last = cur;   //将当前字符个数赋给last
                cur = 1;
            }
            if(last >= cur)
                count++;
        }
        return count;
    }
};  

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章