題目連結:
題目意譯:
一個括號字串為一個只由 '(' 和 ')' 組成的非空字串。而如果下列任何一個條件為真,則該括號字串為合法的:
其為 ()。
可以被寫作 AB(A 與 B 串接),其中 A 和 B 為合法括號字串。
可以被寫作 (A),其中 A 為一個合法括號字串。
你被給定一個括號字串 s 以及一個字串 locked,兩者長度皆為 n。locked 為一個只由 '0' 和 '1' 組成的二元字串。對於 locked 的每一個索引值:
如果 locked[i] 為 '1',則你不得改變 s[i]。
反之如果 locked[i] 為 '0',則你可以將 s[i] 變為 '(' 或 ')'。
如果你可以讓 s 變為一個合法括號字串,則回傳真(True);反之,回傳假(False)。
限制:
n == s.length == locked.length
1 ≦ n ≦ 10 ^ 5
s[i] 只會是 '(' 或 ')'。
locked[i] 只會是 '0' 或 '1'。
範例測資:
範例 1:
輸入: s = "))()))", locked = "010100"
輸出: true
解釋: locked[1] == '1' 且 locked[3] == '1',所以我們無法改變 s[1] 和 s[3]。
我們將 s[0] 和 s[4] 變為 '(',而 s[2] 和 s[5] 不變來使得 s 合法。
範例 2:
輸入: s = "()()", locked = "0000"
輸出: true
解釋: 我們不需要做任何改變,因為 s 已經合法了。
範例 3:
輸入: s = ")", locked = "0"
輸出: false
解釋: locked 允許我們改變 s[0]。
不論是將 s[0] 變為 '(' 還是 ')' 都不會讓 s 變為合法。
解題思維:
首先,很明顯地當 s 的長度為奇數時,不可能讓 s 變成合法的括號字串。因此直接回傳假即可。
接著我們可以從左至右掃過一次 s 並盡量地把看到的括號變成左括號(也就是說,唯一不會變的是 s[i] == ')' 且 locked[i] == '1' 時)。而如一般的括號配對(如
這題),一旦當前左括號的數量 < 右括號的數量時,則代表這個括號字串不合法。而因為我們已經有盡量多的左括號了,所以我們不可能將 s 變為合法。因此此時回傳假。
同樣地,從右至左再掃過一次 s 並盡量將括號變成右括號。然後一旦中途發生右括號的數量 < 左括號的數量時,代表 s 不可能變為合法括號字串。因此此時回傳假。
而如果以上兩者都可以通過,則 s 可以變為合法的括號字串。因此回傳真。
不過說實話,我已經不記得「為何判斷完盡量各自變成左右括號是可行的,代表 s 一定可以變成合法括號字串」的證明或是直覺了。
而且現在重新想目前也沒有頭緒。因此如果有讀者有想法可以煩請分享給大家,感謝。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。