1. 程式人生 > >[LeetCode] Count Binary Substrings 統計二進位制子字串

[LeetCode] Count Binary Substrings 統計二進位制子字串

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.

這道題給了我們一個二進位制字串,然後我們統計具有相同0和1的個數,且0和1各自都群組在一起(即0和1不能交替出現)的子字串的個數,題目中的兩個例子也很能說明問題。那麼我們來分析題目中的第一個例子00110011,符合要求的子字串要求0和1同時出現,那麼當第一個1出現的時候,前面由於前面有兩個0,所以肯定能組成01,再遇到下一個1時,此時1有2個,0有2個,能組成0011,下一個遇到0時,此時0的個數重置為1,而1的個數有兩個,所以一定有10,同理,下一個還為0,就會有1100存在,之後的也是這樣分析。那麼我們可以發現我們只要分別統計0和1的個數,而且如果當前遇到的是1,那麼只要之前統計的0的個數大於當前1的個數,就一定有一個對應的子字串,而一旦前一個數字和當前的數字不一樣的時候,那麼當前數字的計數要重置為1。所以我們遍歷元陣列,如果是第一個數字,那麼對應的ones或zeros自增1。然後進行分情況討論,如果當前數字是1,然後判斷如果前面的數字也是1,則ones自增1,否則ones重置為1。如果此時zeros大於ones,res自增1。反之同理,如果當前數字是0,然後判斷如果前面的數字也是0,則zeros自增1,否則zeros重置為1。如果此時ones大於zeros,res自增1。參見程式碼如下:

解法一:

class Solution {
public:
    int countBinarySubstrings(string s) {
        int zeros = 0, ones = 0, res = 0;
        for (int i = 0; i < s.size(); ++i) {
            if (i == 0) {
                (s[i] == '1') ? ++ones : ++zeros;
            } else {
                if (s[i] == '1'
) { ones = (s[i - 1] == '1') ? ones + 1 : 1; if (zeros >= ones) ++res; } else if (s[i] == '0') { zeros = (s[i - 1] == '0') ? zeros + 1 : 1; if (ones >= zeros) ++res; } } } return res; } };

下面這種方法更加簡潔了,不用具體的分0和1的情況來討論了,而是直接用了pre和cur兩個變數,其中pre初始化為0,cur初始化為1,然後從第二個數字開始遍歷,如果當前數字和前面的數字相同,則cur自增1,否則pre賦值為cur,cur重置1。然後判斷如果pre大於等於cur,res自增1。其實核心思想跟上面的方法一樣,只不過pre和cur可以在0和1之間切換,參見程式碼如下:

解法二:

class Solution {
public:
    int countBinarySubstrings(string s) {
        int res = 0, pre = 0, cur = 1, n = s.size();
        for (int i = 1; i < n; ++i) {
            if (s[i] == s[i - 1]) ++cur;
            else {
                pre = cur;
                cur = 1;
            }
            if (pre >= cur) ++res;
        }
        return res;
    }
};

類似題目:

參考資料: