开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
解题思路
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入: s = "(()"
输出: 2
解释: 最长有效括号子串是 "()"
示例 2:
输入: s = ")()())"
输出: 4
解释: 最长有效括号子串是 "()()"
示例 3:
输入: s = ""
输出: 0
提示:
0 <= s.length <= 3 * 104s[i]为'('或')'
解题思路
- 对于题目,要找最长的括号匹配,也就是找一个开始和结束位置,使得左括号数=右括号数。
- 如果我们用双指针,右指针向右移动,遇到括号计数,并判断当左括号数=右括号数更新答案,当左括号数<=右括号数,说明无法完成匹配,进行重置计数并移动左指针的位置。这样子会发现有一个问题,就是左括号的位置不对,左括号数>右括号数时,也可能会有匹配的地方,而左括号位置不对。
- 所以我们要确定正确的左括号位置,排除不可能的情况。可以先从右向左遍历并计数,如果左括号数>右括号数,说明这个左括号不可以为开始的位置。然后再用上述办法再从左向右遍历即可。
func longestValidParentheses(s string) int {
if len(s) <= 1 {
return 0
}
ss := []byte(s)
l, r := 0, 0
for i := len(ss) - 1; i >= 0; i-- {
if s[i] == '(' {
l++
if l > r {
ss[i] = 'x'
l,r=0,0
}
}else {
r++
}
}
l,r = 0,0
ans := 0
for i := 0; i < len(ss); i++ {
if ss[i]=='x'{
l,r = 0,0
}else if ss[i]=='('{
l++
}else {
r++
if l==r{
ans = max(ans,l)
}else if r>l{
l,r = 0,0
}
}
}
return ans*2
}
func max(a int,b int) int {
if a>b{
return a
}
return b
}
- 当然不想遍历两边,也可以用栈存储左括号的位置,提供入栈出栈两两匹配,也可以得到正确的长度。
start, top := -1, 0
ss := make([]int, len(s))
ans := 0
for i := 0; i < len(s); i++ {
if s[i] == '(' {
ss[top] = i
top++
} else {
if top > 0 {
top--
if top == 0 {
ans = max(ans, i-start)
} else {
ans = max(ans, i-ss[top-1])
}
} else {
start = i
}
}
}
return ans