自我总结使用
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode-solution/
来源:力扣(LeetCode)
//方法1 动态规划
func longestValidParentheses(s string) int {
//动态规划公式:dp[i] = 2 + dp[i-1] + dp[i-dp[i-1]-2]
var max int
length := len(s)
if length < 2 {
return 0
}
dp := make([]int, length)
//这里i从1开始是因为go切片index从0开始
for i := 1; i < length; i ++ {
//判断最长子串dp结尾是不是右括号
if string(s[i]) == ")" {
//判断前一个是不是左括号
if string(s[i-1]) == "(" {
//当前括号的数量是不是大于4个 才能涉及到状态转换方程公式
if i - 1 >= 2 {
//这里我理解是连续的括号 2是本身()长度为2
//再加上当前索引向前推2个就是前一个括号的索引位置子串最大长度
dp[i] = 2 + dp[i-2]
}else{
//只有一对括号的时候长度就是2
dp[i] = 2
}
}else{
//这里如果有连续的右括号说明可能有连续的左括号 那么需要找到满足成对数量的最左侧的左括号(索引是:i-dp[i-1]-1)
//因为这个左括号索引不能为负数 索引判断大于等于0 满足大于等于0之后就去找这个位置是不是左括号
if i - dp[i-1] >= 1 && string(s[i-dp[i-1]-1]) == "(" {
//这里为了满足go 切片索引从0开始 所以对dp[i-dp[i-1]-2]中索引判断大于等于0 简化就是下面写法
if i - dp[i-1] >= 2 {
//满足公式说明左侧有最长子串长度的dp数值 但是整个数值不一定就是大于0的 个人理解
dp[i] = 2 + dp[i-1] + dp[i-dp[i-1]-2]
}else{
//不满足说明左侧只有最左侧的当前这个左括号了也就不需要考虑dp[i-dp[i-1]-2]这部分了
dp[i] = 2 + dp[i-1]
}
}
}
}
//综上所述 取最大长度即可
if max < dp[i] {
max = dp[i]
}
}
return max
}
//方法2 栈
func longestValidParentheses(s string) int {
var max, maxLength int
length := len(s)
var stack []int
//使用-1来先入栈 作为后续计算最大长度使用
stack = append(stack, -1)
for i:=0; i<length; i++ {
if string(s[i]) == "(" {
//左括号入栈
stack = append(stack, i)
}else{
if len(stack) == 0 {
stack = append(stack, i)
max = 0
}else{
if stack[len(stack)-1] == -1 {
stack = []int{}
stack = append(stack, i)
}else{
if string(s[stack[len(stack)-1]]) == "(" {
stack = stack[:len(stack)-1]
//这里max计算是 用当前的索引将或者连续左括号弹出取下一个索引相差就是max
max = (i - stack[len(stack)-1])
}else{
stack = append(stack, i)
}
}
}
}
if maxLength < max {
maxLength = max
}
}
return maxLength
}
//方法三 正向逆向结合法
func longestValidParentheses(s string) int {
if len(s) < 2 {
return 0
}
leftNum, rightNum, maxLength := 0,0,0
//每次遍历比较左右括号数量
//正向比较右括号大于左括号数量 左右括号计数清0
//逆向与之相反
for i := 0; i < len(s); i++ {
if string(s[i]) == "(" {
leftNum++
}else{
rightNum++
}
if rightNum == leftNum {
if maxLength < leftNum {
maxLength = leftNum
}
}
if rightNum > leftNum {
leftNum = 0
rightNum = 0
}
}
leftNum1, rightNum1, maxLength1 := 0,0,0
for i:= len(s)-1; i >= 0; i-- {
if string(s[i]) == ")" {
rightNum1++
}else{
leftNum1++
}
if leftNum1 == rightNum1 {
if maxLength1 < leftNum1 {
maxLength1 = leftNum1
}
}
if leftNum1 > rightNum1 {
leftNum1=0
rightNum1=0
}
}
if maxLength > maxLength1 {
return maxLength*2
}else{
return maxLength1*2
}
}