題目連結:
題目意譯:
你被給定一個陣列 arr 其只由零和一組成,將陣列分成三個非空部分使其滿足所有部分皆代表著同一個二進位數值。
如果可行,回傳任一個 [i, j] 其中 i + 1 < j ,並滿足:
arr[0] 、 arr[1] 、 ……、 arr[i] 為第一部分;
arr[i + 1] 、 arr[i + 2] 、 …… 、 arr[j - 1] 為第二部分,且
arr[j] 、 arr[j + 1] 、 …… 、 arr[arr.length - 1] 為第三部分。
而三個部分皆為相同的二進位數值。
如果不可行,則回傳 [-1, -1]。
注意整個部分應一同視為其表示的二進位數值之一部分。例如,[1, 1, 0] 代表的是十進位的 6,而非 3。且前導零可被允許,因此 [0, 1, 1] 和 [1, 1] 代表著相同的值。
限制:
3 ≦ arr.length ≦ 3 × 10 ^ 4
arr[i] 為 0 或 1。
範例測資:
範例 1:
輸入: arr = [1,0,1,0,1]
輸出: [0,3]
範例 2:
輸入: arr = [1,1,0,1,1]
輸出: [-1,-1]
範例 3:
輸入: arr = [1,1,0,0,1]
輸出: [0,2]
解題思維:
可以看到當三個部分所代表的數值相同時,其各自「1」的數量應相同(「0」則不一定,因為可以有前導零)。不過這不代表著我們可以反過來藉由「1」數量相同這件事判斷數值是否相同。例如 [1, 0, 1] 、 [1, 1, 0] 、 [0, 1, 1] 這三個部分都有著相同數量的「1」,但是數值不相等。
但是這提供了我們一個線索:當 arr 中「1」的總數(在此定為 K 個)不為三的倍數時,我們不可能將 arr 分為三個數值相等的部分;反之,則「有可能」可以分成三部分。
那麼我們要怎麼檢查可不可能分成三部分呢?作法很簡單,我們將前 K ÷ 3 個分給第一部分、中間 K ÷ 3 個分給第二部分、最後 K ÷ 3 個分給第三部分。而因為可能存在前導零,因此我們從第一部分的最左側的「1」(即 arr 的第一個「1」)、第二部分最左側的「1」(即 arr 的第 K ÷ 3 + 1 個「1」)以及第三部分最左側的「1」(即 arr 的第 2(K ÷ 3) + 1 個「1」)開始比對這三個部分的內容。如果內容相同則代表著數值相同(因為二進位表示法將會是相同的)。
假設現在第一部分位於 arr[i]、第二部分位於 arr[j]、第三部分位於 arr[k]。我們便重複以下步驟:
先比對 arr[i] 、 arr[j] 、 arr[k] 這三個是不是彼此相等。如果不相等,就代表我們不可能將 arr 分為三個數值相等的部分,此時回傳 [-1, -1]。
如果皆相等,則將 i 、 j 、 k 皆加上 1(即三個部分同時往右一格去檢查)。直到我們的 arr[k] 碰到 arr 的結尾,無法再往右移動為止。
如果中途的比較都相同,則代表每個部分的二進位表示法之內容皆相同,因此即代表著我們找到了一個分割方式,即 [i - 1, j]。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。