1. 程式人生 > 實用技巧 >【LeetCode】696. 計數二進位制子串

【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”字元。

解題思路

我們可以將字串 s 按照 0 和 1的連續段分組,存在counts 陣列中,例如 s = 00111011可以得到這樣的counts 陣列:{counts} = {2, 3, 1, 2};counts陣列中的兩個相鄰的數一定代表著兩種不同的資料,經過觀法可以發現,兩種不同資料組成的滿足條件的子串數目=min(a,b);

例如00111,counts = {2,3},能組成的滿足條件的子串數目=min(2,3) = 2,經過驗證確實為2

AC程式碼

解法一:

兩次遍歷,空間複雜度時間複雜度都為O(n)

class Solution {
    public int countBinarySubstrings(String s) {
        ArrayList<Integer> ls = new ArrayList<Integer>();
        int num = 1;
        for(int i = 1; i < s.length(); i++){
            if(s.charAt(i) == s.charAt(i-1)) num++;
            else{
                ls.add(num);
                num = 1;
            }
        }
        ls.add(num);
        int ans = 0;
        for(int i = 1; i < ls.size(); i++){
            ans += Math.min(ls.get(i),ls.get(i-1));
        }
        return ans;
    }
}

解法二:

解法二是對解法一的優化,理解了解法一,解法二就非常容易理解了,

一次遍歷,空間複雜度O(1)時間複雜度O(n)

class Solution {
    public int countBinarySubstrings(String s) {
        int num = 1;
        int anoth = 0;
        int ans = 0;
        for(int i = 1; i < s.length(); i++){
            if(s.charAt(i) == s.charAt(i-1)){
                num++;
            }else{
                ans += Math.min(num,anoth);
                anoth = num;
                num = 1;
            }
        }
        ans += Math.min(num,anoth);
        return ans;

    }
}