【leet-code清晰解题思路💯✅】32. 最长有效括号

62 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

解题思路

给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

输入: s = "(()"
输出: 2
解释: 最长有效括号子串是 "()"

示例 2:

输入: s = ")()())"
输出: 4
解释: 最长有效括号子串是 "()()"

示例 3:

输入: s = ""
输出: 0

提示:

  • 0 <= s.length <= 3 * 104
  • s[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
}

image.png

  • 当然不想遍历两边,也可以用栈存储左括号的位置,提供入栈出栈两两匹配,也可以得到正确的长度。
	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

image.png