2021-07-03:给定一个只由左括号和右括号的字符串,返回最长的有效括号子串的长度。

Posted 福大大架构师每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-07-03:给定一个只由左括号和右括号的字符串,返回最长的有效括号子串的长度。相关的知识,希望对你有一定的参考价值。

2021-07-03:给定一个只由左括号和右括号的字符串,返回最长的有效括号子串的长度。

福大大 答案2021-07-03:

1.正向反向。时间复杂度:O(N)。空间复杂度:O(1)。
用栈的思想。遇到(,left加1;遇到),right加1。这个容易想到。
只有当left==right的时候,才统计长度。这个很难想到。
先正向求出长度,然后反向求出长度。这个很难想到。
2.动态规划。时间复杂度:O(N)。空间复杂度:O(N)。

代码用golang编写。代码如下:

package main

import "fmt"

func main() {
    s := "(()()"

    //正向反向
    ret := longestValidParentheses(s)
    fmt.Println("正向反向:", ret)

    //动态规划
    ret2 := longestValidParentheses2(s)
    fmt.Println("动态规划:", ret2)
}

func longestValidParentheses(s string) int {
    N := len(s)
    if N <= 1 {
        return 0
    }
    return getMax(longestValidParenthesesZheng(s), longestValidParenthesesFan(s))
}

func longestValidParenthesesZheng(s string) int {
    N := len(s)
    ans := 0
    left := 0
    right := 0
    for i := 0; i < N; i++ {
        if s[i] == '(' {
            left++
        } else {
            right++
        }
        if left == right {
            ans = getMax(ans, left)
        } else if right > left {
            left = 0
            right = 0
        }
    }
    return ans * 2
}

func longestValidParenthesesFan(s string) int {
    N := len(s)
    ans := 0
    left := 0
    right := 0
    for i := N - 1; i >= 0; i-- {
        if s[i] == '(' {
            left++
        } else {
            right++
        }
        if left == right {
            ans = getMax(ans, left)
        } else if left > right {
            left = 0
            right = 0
        }
    }
    return ans * 2
}

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

// s只由(和)组成
// 求最长有效括号子串长度
func longestValidParentheses2(s string) int {
    if len(s) < 2 {
        return 0
    }
    // dp[i] : 子串必须以i位置结尾的情况下,往左最远能扩出多长的有效区域
    dp := make([]int, len(s))
    // dp[0] = 0; (  )
    pre := 0
    ans := 0
    for i := 1; i < len(s); i++ {
        if s[i] == ')' {
            // 当前谁和i位置的),去配!
            pre = i - dp[i-1] - 1 // 与str[i]配对的左括号的位置 pre
            if pre >= 0 && s[pre] == '(' {
                if pre > 0 {
                    dp[i] = dp[i-1] + 2 + dp[pre-1]
                } else {
                    dp[i] = dp[i-1] + 2
                }
            }
        }
        ans = getMax(ans, dp[i])
    }
    return ans
}

执行结果如下:
图片


左神java代码

以上是关于2021-07-03:给定一个只由左括号和右括号的字符串,返回最长的有效括号子串的长度。的主要内容,如果未能解决你的问题,请参考以下文章

括号匹配

如何在 C++ 中对以下字符串序列进行排序?

所涉及的递归调用到底发生了啥?

数据结构大师(求区间最长合法括号子序列)

如何在 c++ 中将字符串拆分为左括号和右括号之间的字符串列表?

LeetCode - 20 :有效的括号