32.最长有效括号
题解
题目:求匹配括号的最长长度
思路一 栈
遍历字符串
1.如果是(,则入栈
2.如果是),如果栈空,说明这个右括号是多于的,将对应的mark置1
如果栈不空,则弹出栈顶
3.遍历栈,如果栈里还有没有被弹出的(,将对应的mark置1
4.计算连续0的长度,即计算最长可用长度
思路二 dp
dp[i]表示以s[i]字符结尾的最长有效长度
如果s[i]== (
- 左括号不能与前面的元素匹配,所以dp[i]=0
如果s[i]== )
- 如果s[i-1]== (
-
- 说明构成了()的形式,那么有效长度增加2,即dp[i]=dp[i-2]+2
-
- 如果s[i-1]== )
-
- 说明构成了xxx ))的形式,这个时候想要形成(())的形式,需要要求s[i-1]的位置是匹配的,如果s[i-1]不匹配,s[i]则不能与前面的(匹配
-
- 所以判断s[ i-1-dp[i-1] ] 是否为(
-
-
- 如果s[ i-1-dp[i-1] ]== ( ,说明 i-1-dp[i-1]的左括号和i的右括号匹配,则dp[i]=dp[i-2]+2
-
-
-
- 但是这里只是考虑了(())的情况,如果是()(())的情况呢?前面的()的长度我们也要加上,所以dp[i] = dp[i-1] + 2 + dp[i-2-dp[i-1]]
-
-
-
综上所述,dp的状态转移方程为
dp[i] = dp[i-2] + 2 //xxxx()
dp[i] = dp[i-1] + 2 + dp[i-2-dp[i-1]] //()(())
思路三 贪心 遍历两次
我们知道有效括号代表这能够匹配,那么
- 遇到(,left++ 遇到) right++
- 如果left=right,说明匹配成功
- 如果left<right,这个情况的前面相等时的长度已经记录过了,直接将left和right置为0
- 但是(()这种情况,将没有答案
- 这个时候倒着再遍历一遍,将第三步改为如果left>right即可
代码
func longestValidParentheses(s string) int {
mark := make([]int, len(s))
stack := make([]int, 0)
for i, ch := range s {
if ch == '(' { //如果是(,则入栈
stack = append(stack, i)
}
if ch == ')' { //如果是)
if len(stack) == 0 { //如果是多余的),说明该位置不可用
mark[i] = 1
} else {
stack = stack[:len(stack)-1] //不是多余的,则弹出一个(
}
}
}
for _, idx := range stack { //还在栈里面没有被匹配的(,都不可用
mark[idx] = 1
}
ans, temp := 0, 0
for i := 0; i < len(mark); i++ { //计算最长可用长度
if mark[i] == 1 {
temp = 0
} else {
temp++
ans = max(ans, temp)
}
}
return ans
}
func max(i, j int) int {
if i > j {
return i
}
return j
}
func longestValidParentheses(s string) int {
ans := 0
dp := make([]int, len(s))
for i := 1; i < len(s); i++ {
ch := s[i]
if ch == '(' {
dp[i] = 0
} else if ch == ')' {
if s[i-1] == '(' {
if i-2 >= 0 {
dp[i] = dp[i-2] + 2 //xxxx()
} else {
dp[i] = 2 //()
}
} else if s[i-1] == ')' {
if i-1-dp[i-1] >= 0 && s[i-1-dp[i-1]] == '(' {
if i-2-dp[i-1] >= 0 {
dp[i] = dp[i-1] + 2 + dp[i-2-dp[i-1]] //()(())
} else {
dp[i] = dp[i-1] + 2 //(())
}
}
}
}
ans = max(ans, dp[i])
}
return ans
}
func max(i, j int) int {
if i > j {
return i
}
return j
}
func longestValidParentheses(s string) int {
left, right := 0, 0
ans := 0
for _, v := range s {
if v == '(' {
left++
} else {
right++
}
if left == right {
ans = max(ans, left+right)
}
if right > left {
left, right = 0, 0
}
}
left, right = 0, 0
for i := len(s) - 1; i >= 0; i-- {
v := s[i]
if v == '(' {
left++
} else {
right++
}
if left == right {
ans = max(ans, left+right)
}
if left > right {
left, right = 0, 0
}
}
return ans
}
func max(i, j int) int {
if i > j {
return i
}
return j
}