題目連結:
題目意譯:
你被給定一個二元字串 binary。一個 binary 的子序列會被視為是「好的」如果它非空且沒有任何前導零(除了 "0" 本身以外)。
找到 binary 中彼此相異的好子序列之數量為何。
例如,如果 binary = "001",則所有好的子序列為 ["0", "0", "1"],因此相異的好子序列為 "0" 和 "1"。注意,子序列 "00" 、 "01" 和 "001" 不是好的,因為它們有著前導零。
回傳 binary 中彼此相異的好子序列之數量。由於答案可能很大,將其模 10 ^ 9 + 7 後回傳。
一個子序列為一序列其可藉由從另一個序列刪除若干個或是不刪除任何元素並不更動剩餘元素的順序的情況下得到。
限制:
1 ≦ binary.length ≦ 10 ^ 5
binary 只會有 '0' 和 '1' 組成。
範例測資:
範例 1:
輸入: binary = "001"
輸出: 2
解釋: 好的子序列為 ["0", "0", "1"]。
相異的好子序列為 "0" 和 "1"。
範例 2:
輸入: binary = "11"
輸出: 2
解釋: 好的子序列為 ["1", "1", "11"]。
相異的好子序列為 "1" 和 "11"。
範例 3:
輸入: binary = "101"
輸出: 5
解釋: 好的子序列為 ["1", "0", "1", "10", "11", "101"]。
相異的好子序列為 "0" 、 "1" 、 "10" 、 "11" 和 "101"。
解題思維:
因為我們需要找出所有不是零開頭(除了 "0")的子序列,因此我們可以利用動態規劃(Dynamic Programming)來求得所求。
定義兩個變數 X 、 Y,依序分別用來儲存 0 開頭的子序列數量以及 1 開頭的子序列數量(初始值為 0)。接著我們從 binary 這個字串的右邊掃到左邊,其中不是由左至右是因為我們要關心的是「開頭」,而不是結尾。
當我們遇到 '0' 時,代表這個 '0' 可以作為先前的(即較右側的)任意子序列的開頭或是自己作為一個長度為 1 的子序列。因此 X 之值應更新為 X + Y + 1;同理,遇到 '1' 時,我們應將 Y 更新為 X + Y + 1。而為了讓結尾不要太大,所以計算過程中需時時取 10 ^ 9 + 7 的餘數。
掃完之後,Y 之值幾乎就是所求了。接著我們判斷一下,binary 中有沒有 '0' 出現(請不要用 X 之值來判斷,因為 X 有可能取餘數後變成 0。再不然應使用另一個變數來代表有沒有出現過 '0'),因為 "0" 這個子序列是唯一一個可以有前導零的子序列。如果有則所求為 Y + 1;反之則為 Y。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。