Hard草稿★★★★O(n) 時間 · O(n) 空間
StringStackDynamic Programming
Patterns🥞 堆疊
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

32Longest Valid ParenthesesStackHardStack

給定只含 '('')' 的字串,求最長「有效(格式正確且連續)」括號子字串的長度。

Example:

Input: s = ”(()” Output: 2(”()”)

Input: s = ”)()())” Output: 4(”()()”)

Input: s = "" Output: 0

Intuition

TIP

核心思路:用堆疊存「索引」並放一個基準 -1。每遇 ) 就彈出,若堆疊空了就把當前索引當新基準,否則用 i - 堆疊頂端 算出當前有效長度。

Approaches

⭐ 1. Stack of Indices + Base -1 — O(n) / O(n)
  • Idea: 堆疊維護未匹配位置;有效長度 = 當前索引 − 上一個未匹配位置
  • Time: O(n)
  • Space: O(n) - 堆疊
class Solution {
    fun longestValidParentheses(s: String): Int {
        val stack = ArrayDeque<Int>()
        stack.addLast(-1)   // 基準
        var maxLen = 0
        for (i in s.indices) {
            if (s[i] == '(') {
                stack.addLast(i)
            } else {
                stack.removeLast()
                if (stack.isEmpty()) {
                    stack.addLast(i)   // 沒有可匹配的 '(',當前位置成為新基準
                } else {
                    maxLen = maxOf(maxLen, i - stack.last())
                }
            }
        }
        return maxLen
    }
}
2. Left/Right Count, Two Passes — O(n) / O(1)
  • Idea: 正掃計左右括號數,相等就更新;右括號多則歸零。反掃再做一次以涵蓋 ”(((” 的情況
  • Time: O(n)
  • Space: O(1) - 不用額外空間
class Solution {
    fun longestValidParentheses(s: String): Int {
        var maxLen = 0
        var left = 0; var right = 0
        for (c in s) {
            if (c == '(') left++ else right++
            if (left == right) maxLen = maxOf(maxLen, 2 * right)
            else if (right > left) { left = 0; right = 0 }
        }
        left = 0; right = 0
        for (i in s.indices.reversed()) {
            if (s[i] == '(') left++ else right++
            if (left == right) maxLen = maxOf(maxLen, 2 * left)
            else if (left > right) { left = 0; right = 0 }
        }
        return maxLen
    }
}

🔑 Takeaways