LeetCode32-最长有效括号
最近这两天有断更了,大家知道是为什么吗?肯定不是因为是我懒哈(大家想要笑也要憋着)这两天一直在研究回溯法,被折磨的死去活来的。终于是有些收获了,所以会在这两天再把我的一些关于解回溯法题目的心得分享出来,希望大家会有些收获。写的都会是很通俗易懂的大白话,会教大家怎么写递归的过程,因为回溯法虽然好用,但是如何写出这个过程一直很麻烦,因为其抽象性比较高,很容易就被它搞糊涂了。而我这两天在网上找的资料都是千篇一律,基本上都是把一些现货炒来炒去,害人不浅!!!大家敬请期待我的文章。
32-最长有效括号
给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
这一题算是20题有效的括号进阶版了,因为是要求最长的,所以我们必须是得存储一个字符串中所有有效括号的长度信息,再从里面选取长度最大值即可,这算是最直接的思路了。我第一次也是这样做的。
思路:
- 首先用20题求解有效括号的方法(进栈出栈)求得给定字符串中所有有效括号的成对下标值,并保存在一List列表中。
- 因为成对括号下标可能相邻也可能相差大于1,但是下标排序后连续且相差1的下标串对应的字符串必然是合法结构,所以我只需要将1中得到的列表中的值做sort()排序操作。
- 依次检查相邻下标值相差为1的下标最大个数,取最大值即为所求的最长有效括号的长度
代码如下:
class Solution:
# 本题还是采用较典型的进栈出栈法
# 字典再添加元素时key值并不是按照从小到大排列的,顺序是混乱的
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
if len(s) == 0 or len(s) == 1:
return 0
s_list = list(s)
# 定义一个字典用做栈,方便做进栈入栈操作,字典key值为括号对应的下标值,value值为相应的括号
s_queue = {0: s[0]}
# 定义一个List列表用于保存一对有效括号的两个下标值
max_s_length = []
for s_index in range(1, len(s_list)):
# 只有当元素为')'才能出栈,此时要比较栈顶元素,
# 如果栈顶元素也就是s_queue[s_queue_lastkey]为'('则可以出栈,反之则不行
if len(s_queue) > 0 and s_list[s_index] == ")":
# 字典再添加元素时key值并不是按照从小到大排列的,顺序是混乱的,所以一定要把key值排序
# 这样才能每次拿到s_queue字典最后一个值,也就是栈顶元素
s_queue_keys = list(s_queue.keys())
s_queue_keys.sort()
s_queue_lastkey = s_queue_keys[-1]
print("s_queue_lastkey", s_queue_lastkey)
# 如果栈顶元素也就是s_queue[s_queue_lastkey]为'('则可以出栈
if s_queue[s_queue_lastkey] == "(":
print("[s_queue_lastkey, s_index]", [s_queue_lastkey, s_index])
max_s_length.extend([s_queue_lastkey, s_index])
s_queue.pop(s_queue_lastkey)
# 只有当元素为'('才能进栈,也就是s_queue字典才能保存该key值
else:
s_queue[s_index] = s_list[s_index]
print("s_queue", s_queue)
# 有效括号的下标值得到后排序,并对里面相邻的值检查,即可得到最大长度值
# 关键:成对括号下标可能相邻也可能相差大于1,但是下标排序后连续且相差1的下标串对应的字符串必然是合法结构
max_s_length.sort()
if len(max_s_length) == 0:
return 0
print("max_s_length", max_s_length)
length = 1
max_length = 0
# 遍历max_s_length列表,寻找相差为1的下标的最大个数
for index in range(1, len(max_s_length)):
if max_s_length[index] - max_s_length[index-1] == 1:
length += 1
else:
if length > max_length:
max_length = length
length = 1
return max(length, max_length)
if __name__ == "__main__":
s = "))(((()()"
result = Solution().longestValidParentheses(s)
print(result)
这段代码中我做了很多注解,大家应该挺好看懂的,但是执行效率挺差的,只有10%左右。
后来在网上看到了一大佬给的算法,也是采用进栈出栈法,但是它是直接将有效括号对的下标值进行运算得到最大有效长度,真的是牛逼,不知道大佬们是怎么能想到这么简单快捷的骚操作,我也把代码贴出来,大家可以学习学习。
class Solution:
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
tl = len(s)
stack = []
st = 0
maxlen = 0
for i in range(tl):
# 如果是左括号,直接入stack
if s[i] == '(':
stack.append(i)
# 如果右括号
else:
# 如果stack里没有元素匹对,说明有效括号已经结束,更新起始位置
if len(stack) == 0:
st = i + 1
continue
# 有元素匹对
else:
a = stack.pop()
# pop出一个左括号匹对
# 如果此时没了,不能保证不继续有效括号,所以根据当前的最长距离去更新maxlen
if len(stack) == 0:
maxlen = max(i - st + 1, maxlen)
# 如果此时还有 则计算与栈顶的索引相减来计算长度
else:
maxlen = max(i - stack[-1], maxlen)
return maxlen
if __name__ == "__main__":
s = "))(((()()"
result = Solution().longestValidParentheses(s)
print(result)
执行效率也是真的高,再次跪拜大佬!!!