https://leetcode-cn.com/problems/longest-valid-parentheses/
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3:
输入:s = ""
输出:0
提示:
0 <= s.length <= 3 * 104
s[i] 为 '(' 或 ')'
拿到题,这种对称的问题,一般首先想到的都是栈。但是我不一开始就用栈来解决,假设我们一开始没有想法怎么解决。我们首先按照从简到难的顺序一一解决。
思考:
文中数最长有效字符串,我们想到要考虑有哪些情形
比较个数 符号(比符号)多 ( (() 符号)比符号(多 ) ()) 符号(和符号)相同 () |
暴力法:
以每个字符为首字符,寻找其最大的有效长度,(()(c
# 暴力破解法
# 遍历字符串中的每一个字符,以每个字符开头,找到其最大的合法字符。
# 若符号(的个数大于符号)的个数,则可能还是有效的,继续处理
# 若(的个数等于)则统计最大值。
# "(()" 1,以第一个开头未找到合法字符,第二个才找到最大的合法数2
# ()))())())(())
# 遍历数据
# 若)丢弃,跳到下一个
# 若(,继续下面的操作,进行后续遍历。
# 1,统计左右的个数,l,r
# 2,( l+1,) r+1
# 3,若l>r,继续,?,若r=l,则max(2r,maxLen)
# l<r 结束,此字符开头的合法字符串结束。
def brute_search(s: str):
max_len = 0
s_len = len(s)
for i in range(s_len):
if s[i] == "(":
l, r = 0, 0
for j in range(i, s_len):
if s[j] == "(":
l += 1
if s[j] == ")":
r = r + 1
if l == r:
max_len = max(2 * r, max_len)
if l < r:
break
return max_len
if __name__ == "__main__":
s = "()(()"
ans = brute_search(s)
# ans = brute_force(s)
print(ans)
2,栈解决法,记录下标。思维独特,想不出来。
def longestValidParentheses(self, s: str) -> int:
stack: int = [-1, ]
max_len = 0
s_len = len(s)
for i in range(s_len):
if s[i] == "(":
stack.append(i)
elif len(stack) > 1:
stack.pop()
max_len = max(i - stack[-1], max_len)
else:
stack[-1] = i
return max_len
3,动态规划
动态规划最朴素的思路就是拆分问题,将大问题拆分成小问题。但是和分治算法不同的是,动态规划更加关注子问题和原问题之间的逻辑联系,而分治算法可能更加侧重拆分。并且分治算法的拆分通常是基于数据和问题规模的,而动态规划则不然,更加侧重逻辑。除此之外,动态规划也非常注重模式的构造。
我们最经常干的一件事情就是创建一个叫做dp的数组,它来记录每一个位置能够达到的最佳结果。比如在这题当中,最佳结果就是最长匹配的括号串。所以dp[i]就记录以s[i]结尾的字符串能够构成的最长的匹配串的长度。
""" 遍历s,如果遇到s[i]是左括号,则以左括号结尾的最长有效子串一定是零, 直接跳过;如果遇到右括号,则需要根据s[i-1]的情况进行判断。 如果s[i-1]是左括号,说明s[i-1]与s[i]正好凑成一对,dp[i]直接在dp[i-2]的基础上加2即可。 如果s[i-1]是右括号,则需要寻找一下,与当前右括号s[i]配对的左括号应该在哪里, 我们把这个左括号应该在的位置定义为j,有j = i - 1 - dp[i - 1], dp[i-1]即以s[i-1]结尾的有效括号的最大长度, 相当于i位置和j位置的左右括号把dp[i-1]长度的有效子串夹在中间。 这时就需要看了,j位置到底是不是左括号, 如果是左括号,则可以将以j-1结尾的最长有效子串,以i-1结尾的最长有效子串, 以及i和j位置的左右括号一起合并成一个大的有效子串, 长度一共是dp[j-1]+1+dp[i-1]+1,相反, 如果j-1位置处不是左括号,说明当前右括号没有与之匹配的左括号,直接跳过次轮循环即可。 """
def long_parentheses_dy(s: str):
s_len = len(s)
d = s_len * [0]
for i in range(1, s_len):
if s[i] == ")":
if s[i - 1] == "(":
d[i] = 2 + (d[i - 2] if i > 1 else 0)
elif i - d[i - 1] - 1 >= 0 and s[i - d[i - 1] - 1] == "(":
d[i] = d[i - 1] + 2 + (d[i - d[i - 1] - 1 - 1] if i-d[i-1]-2>=0 else 0)
return max(d + [0]) # max([]),[0]
和栈方法大同小异,都是利用下标位置去计算最大的长度
理解动态思想