題目描述:給定一個只包含 '(' 和 ')' 的字串,找出最長的有效(格式正確且連續)括號子字串的長度。
解題思路:我們介紹最直觀的堆疊法。
維護一個堆疊,初始放入哨兵值 -1(代表「上一個無效位置的索引」)。
遍歷每個字元:
'(':將其索引壓入堆疊。')':
'(' 或哨兵)。為什麼初始放 -1? 因為若字串一開始就是有效的(如 "()"),彈出哨兵後堆疊為空,長度 = 1 − (−1) = 2,恰好正確。
DP 方法補充:定義 dp[i] = 以 s[i] 結尾的最長有效括號長度。若 s[i] = ')':若 s[i-1] = '(',則 dp[i] = dp[i-2] + 2;若 s[i-1] = ')' 且 s[i - dp[i-1] - 1] = '(',則 dp[i] = dp[i-1] + dp[i - dp[i-1] - 2] + 2。
時間複雜度:O(n) — 無論是堆疊法還是 DP 法,都只需一次從左到右的線性掃描,每個字元恰好處理一次。
空間複雜度:O(n) — 堆疊法最壞情況下(全是 '(')堆疊深度為 n;DP 法需要 O(n) 的 dp 陣列。若使用雙指標計數法(Two-Pass Counter)可達到 O(1) 空間。
Stack approach:
1. Initialize stack with sentinel value -1
2. Set maxLen = 0
3. For each index i from 0 to n-1:
a. If s[i] == '(': push i onto stack
b. Else (s[i] == ')'):
- Pop top of stack
- If stack is empty: push i as new sentinel
- Else: maxLen = max(maxLen, i - stack.top())
4. Return maxLen
DP approach:
1. Initialize dp[0..n-1] = 0, maxLen = 0
2. For i from 1 to n-1:
a. If s[i] == ')':
- If s[i-1] == '(': dp[i] = dp[i-2] + 2 (if i>=2, else 2)
- Else if dp[i-1] > 0 and s[i - dp[i-1] - 1] == '(':
dp[i] = dp[i-1] + 2 + dp[i - dp[i-1] - 2] (if index valid)
- maxLen = max(maxLen, dp[i])
3. Return maxLen方法一:動態規劃(Dynamic Programming)
定義 dp[i] 為以索引 i 結尾的最長有效括號子字串長度。透過分析 s[i] 和 s[i-1] 的字元組合推導遞推公式。時間複雜度 O(n),空間複雜度 O(n)。優點是邏輯清晰,但需要仔細處理邊界索引。
方法二:雙向掃描計數法(Two-Pass Left-Right Counter)
從左到右掃描,用 left 和 right 計數器分別統計 '(' 和 ')' 的數量:當兩者相等時更新最大長度;當 right > left 時重置兩者。再從右到左做一次相同操作(角色互換)。兩遍掃描合起來覆蓋所有情況。時間複雜度 O(n),空間複雜度 O(1),是空間最優解。
( 和 ) 兩種括號,若同時包含 (、)、[、]、{、} 三種括號,如何找最長有效括號子字串?