最长有效括号——算法

101 阅读2分钟

image.png

动态规划代码1:

  1. dp[i] 表示以下标 i 字符结尾的最长有效括号
  2. 如果 s[i] 是 '(' 结尾则对应的dp一定是 0 ,这种情况不考虑
  3. 当 s[i] == ')' , 则需要判断 s[i-1] 是什么,如果是 '(' ,则状态转移 dp[i] = dp[i-2] + 2
  4. 如果 s[i-1] 是 ')' 且 s[i - dp[i-1]-1] == '(' , 也就是去除前面已成型的括号,那么状态转移 dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2
  5. 当然在状态转移的时候,要保证下标合法
  6. ans则维护dp中的最大值
func longestValidParentheses(s string) int {
    ans := 0
    n := len(s)
    if n < 2 {
        return 0
    }
    dp := make([]int, n)
    if s[:2] == "()" {
        dp[1] = 2
        ans = 2
    }
    for i := 2; i < n; i++ {
        if s[i] == ')' {
            if s[i-1] == '(' {
                dp[i] = dp[i-2] + 2
            }else if i - dp[i-1] -1 >= 0 && s[i - dp[i-1]-1] == '(' {
                if i - dp[i-1] - 2 >= 0 {
                    dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2
                }else {
                    dp[i] = dp[i-1] + 2
                }
            }
            ans = max(ans, dp[i])
        }
    }
    return ans
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

栈代码2:

  1. stk数组模拟栈,保存 '(' 的下标,其中栈底保存多余的右括号的位置,初始为-1
  2. 遍历,碰到 ')' 则弹出栈顶元素,如果栈为空,则将下标压入栈,意味着栈从这里重置,因为遇到了多余的右括号,
  3. 如果栈不为空则维护ans的最大值
func longestValidParentheses(s string) int {
    ans := 0
    stk := []int{-1}
    for i, v := range s {
        if v == '(' {
            stk = append(stk, i)
        }else {
            stk = stk[:len(stk)-1]
            if len(stk) == 0 {
                stk = append(stk, i)
            }else {
                ans = max(ans, i - stk[len(stk)-1])
            }
        }
    }
    return ans
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

代码3:

  1. a , b 用来记录左右括号的数量,当数量相等的时候维护一次最大值
  2. 当左括号数量小于右括号数量则置0,原因其实与前两个方法一致,因为不论后面再出现什么符号,它都无效
  3. 但这种方法有一种情况无法记录,那就是左括号的数量一直大于右括号的数量
  4. 所以为了考虑这种情况,我们可以将s字符串从左往右倒着来一遍1,2,3的步骤
func longestValidParentheses(s string) int {
    ans := 0
    a, b := 0, 0
    for _,v := range s {
        if v == '(' {
            a++
        }else {
            b++
        }
        if a == b{
            ans = max(ans, a * 2)
        }else if a < b {
            a, b = 0, 0
        }
    }
    a, b = 0, 0
    for i := len(s)-1; i >= 0; i-- {
        if s[i] == ')' {
            b++
        }else {
            a++
        }
        if b == a {
            ans = max(ans, b * 2)
        }else if a > b {
            a, b = 0, 0
        }
    }
    return ans
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}