LeetCode32 最长有效括号

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

有效括号:(()), ()()

方法一:暴力法

所谓暴力法,即逐个遍历,遍历的同时判断该子串是否是有效括号。所以,这里需要编写另一个函数,用来判断子串是否是有效的括号组合,然后在主函数中进行遍历。

正好,这有一篇文章来介绍判断有效括号的方法,是使用栈来判断的,文章链接如下:https://www.cnblogs.com/ye8381/articles/12197980.html。有了判断的方法就简单了,就直接给出代码吧:

def longest_valid_parentheses(s: str) -> int:
    
    interval = len(s)
    i = 0
    while i < len(s):
        if is_valid(s[i: i + interval]):
            return interval
        else:
            if i + interval == len(s):
                interval -= 1
                i = 0
            else:
                i += 1
    return 0

# 判断有效括号组合
def is_valid(s: str) -> bool:

        stack = ['#']

        for i in s:
            if i == ')':
                top = stack.pop()
                if top != '(':
                    return False
            else:
                stack.append(i)
        return len(stack) == 1

显然,这个方法很容易想到,也很容易就实现了。但是逐步遍历并且判断,这个效率是不是有点低啊,所以有更好的方法吗?

方法二、栈

这里有一个简单的方法,就是利用栈。

与找到每个可能的子字符串后再判断它的有效性不同,我们可以用栈在遍历给定字符串的过程中去判断到目前为止扫描的子字符串的有效性,同时能的都最长有效字符串的长度。我们首先将 -1−1 放入栈顶。

对于遇到的每个 \text{‘(’}‘(’ ,我们将它的下标放入栈中。
对于遇到的每个 \text{‘)’}‘)’ ,我们弹出栈顶的元素并将当前元素的下标与弹出元素下标作差,得出当前有效括号字符串的长度。通过这种方法,我们继续计算有效子字符串的长度,并最终返回最长有效子字符串的长度。

如果不是很清楚,可以看着代码自己琢磨琢磨。

def longest_valid_parentheses(s: str) -> int:
    max_len = 0
    stack = [-1]
    for i in range(len(s)):
        if s[i] == '(':
            stack.append(i)
        else:
            stack.pop()
            if not stack:
                stack.append(i)
            else:
                max_len = max(max_len, i - stack[-1])
    return max_len

方法三、正反向遍历法

我觉得此方法亮瞎了我的眼,实在是牛逼。哎哎哎!此方法不是我所想出来的,只能说解题者牛逼,真的牛逼。所以这么牛逼的方法,只可意会,不可言传。

算法:

在这种方法中,我们利用两个计数器 left 和 right 。首先,我们从左到右遍历字符串,对于遇到的每个‘(’,我们增加 left 计算器,对于遇到的每个‘)’ ,我们增加 right 计数器。每当 feft 计数器与 right计数器相等时,我们计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串。如果 right计数器比 left计数器大时,我们将 left和 right计数器同时变回 0。

接下来,我们从右到左做一遍类似的工作。(官方解释)

直接上代码,细细琢磨吧。

def longest_valid_parentheses(s: str) -> int:
    left, right, max_len = 0, 0, 0
    for i in s:
        if i == '(':
            left += 1
        else:
            right += 1
        if left == right:
            max_len = max(max_len, 2 * right)
        elif right >= left:
            left = right = 0
    left, right = 0, 0
    for i in s[::-1]:
        if i == '(':
            left += 1
        else:
            right += 1
        if left == right:
            max_len = max(max_len, 2 * left)
        elif left >= right:
            left = right = 0
    return max_len
闪瞎狗眼法
posted @ 2020-01-20 20:12  叶聪  阅读(66)  评论(0)    收藏  举报