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;
    }
};  

 


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