算法特辑–动态规划
Leetcode 32 最长合法括号子序列
给定只有“(” 和 “)” 的字符串,求出最长的合法括号子序列。
例如:"())" ,合法子序列为"()", 最长为2
“((())” 合法子序列为"(())", 最长为4
思路:看到括号首先要想到栈结构,遍历所有元素的时候和栈顶去比较。然后看到最长子序列,可以想到动态规划。整体思路就是先用栈把所有合法的括号子字符串序号放入一个列表中,然后在此列表求最长连续。
- 新建栈stack,第一个元素和当前index入栈。新建序号列表L用于存储合法括号的序号
- 从第二个元素开始遍历,把当前元素和栈顶做比较,如果栈顶是"(",而当前的元素恰好是")", 那么栈顶元素出栈。并将当前元素序号和栈顶元素序号放入L 中。其他情况将当前元素入栈。
- 先将列表排序,在得到的序号列表 L 中用动态规划找到最长的子序列。
代码部分
class Solution:
def longestValidParentheses(self, s: str) -> int:
if len(s)==0:
return 0
//初始化
dp=[]
stack =[]
stack.append((0,s[0]))
//计算合法的子字符串O(n)
for i in range(1,len(s)):
if not stack:
stack.append((i,s[i]))
continue
top_index, top_paren = stack[-1]
if top_paren =='(' and s[i]==')':
index1, paren1 = stack.pop()
dp.append(index1)
dp.append(i)
else:
stack.append((i,s[i]))
//动态规划计算最长的括号序号O(nlogn)+ O(n)
if len(dp)==0:
return 0
dp =sorted(dp)
res_list = [0]*len(dp)
res_list[0]=1
for i in range(1,len(dp)):
if dp[i]==dp[i-1]+1:
res_list[i]=res_list[i-1]+1
else:
res_list[i]=1
return max(res_list)
这道题很经典,属于动态规划和栈结构相结合的题目。整体算法时间复杂度O(nlogn),不知道是否有更优解,但给出的算法比较好想且直观。
@星心火
大数据/全栈/AI算法工程师