码迷,mamicode.com
首页 > 其他好文 > 详细

【LeetCode每日一题】2020.7.04 32. 最长有效括号

时间:2020-07-07 19:44:04      阅读:63      评论:0      收藏:0      [点我收藏+]

标签:动态   每日一题   math   状态   cas   表示   代码   包含   空间   

32. 最长有效括号

给定一个只包含 ‘(‘‘)‘ 的字符串,找出最长的包含有效括号的子串的长度。

示例:

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

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

分析:

? 本题可以用动态规划解决。动态规划的结构是,括号字符串的下标i,dp[i]则表示前i个字符中最长有效括号的长度

? 接着考虑转移方程,

  1. \(s[i] == \ ‘)‘ \ and\ s[i - 1] == \ ‘(‘\):

    可以判断出至少有一对匹配成功,如"......()......"。

    如果字符串为"...((()",则也是只有一对匹配。

    但如果字符串为"...()()()",则\(dp[i] = dp[i - 2] + 2\),即将之前的有效结果加上。

    归纳一下,即:

    \(dp[i] = dp[i - 2] + 2,\ if s[i] == ‘)‘ and s[i - 1]==‘(‘\)

    • 同时应该注意边界条件
  2. 如果字符串类似"...((()))",对于最后一个下标如何进行状态转移?

    首先,最里层嵌套括号对右括号dp结果应该为2,接着到第二层括号的右括号")",往左寻找是否有对应的左括号"("。如何寻找那个应该与他对应的左括号呢?只要下标减去中间有效括号的长度即可。同时,应该注意查找前面是否还有一段有效括号。即:

    \(dp[i] = \begin{cases}dp[i-1] + 2 \text{, if s[i] == ‘)‘ and s[i-1] == ‘)‘ and s[i - s[i - 1] - 1] == ‘(‘} \end{cases}\)

    • 同时应该注意边界条件

? 官方题解还给出了利用 来判断括号匹配关系,以及一种 不需要额外空间的方法。

代码(Golang):

// 一、动态规划:
func longestValidParentheses(s string) int {
	maxAns := 0
	dp := make([]int, len(s))
	for i := 1; i < len(s); i++ {
		if s[i] == ‘)‘ {
			if s[i - 1] == ‘(‘ {
				if i >= 2 {
					dp[i] = dp[i - 2] + 2
				} else {
					dp[i] = 2
				}
			} else if i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == ‘(‘ {
				if i - dp[i - 1] >= 2 {
					dp[i] = dp[i - 1] + dp[i - dp[i - 2] - 2] + 2
				} else {
					dp[i] = dp[i - 1] + 2
				}
			}
			maxAns = max(maxAns, dp[i])
		}
	}
}

func max(nums ...int) int {
	max := nums[0]
	for i := 1; i < len(nums); i++ {
		if nums[i] > max {
			max = nums[i]
		}
	}
	return max
}


// 二、栈:
func longestValidParentheses1(s string) int {
	maxAns := 0
	var stack []int
	stack = append(stack, -1)
	for i := 0; i < len(s); i++ {
		if s[i] == ‘(‘ {
			stack = append(stack, i)
		} else {
			stack = stack[:len(stack) - 1]
			if len(stack) == 0 {
				stack = append(stack, i)
			} else {
				maxAns = max(maxAns, i - stack[len(s) - 1])
			}
		}
	}
	return maxAns
}


// 三、不需要额外的空间:
func longestValidParentheses2(s string) int {
	left, right, maxLength := 0, 0, 0
	for i := 0; i < len(s); i++ {
		if s[i] == ‘(‘ {
			left++
		} else {
			right++
		}
	}
	if left == right {
		maxLength = max(maxLength, 2 * right)
	} else if left > right {
		left, right = 0, 0
	}
	return maxLength
}

【LeetCode每日一题】2020.7.04 32. 最长有效括号

标签:动态   每日一题   math   状态   cas   表示   代码   包含   空间   

原文地址:https://www.cnblogs.com/enmac/p/13262590.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!