LeetCode 32 最长有效括号 - Go语言中文社区

LeetCode 32 最长有效括号


LeetCode 32 最长有效括号

题目

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

示例 1:

输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”
示例 2:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析

方法 1:暴力
算法

在这种方法中,我们考虑给定字符串中每种可能的非空偶数长度子字符串,检查它是否是一个有效括号字符串序列。为了检查有效性,我们使用栈的方法。

每当我们遇到一个 text{‘(’}‘(’ ,我们把它放在栈顶。对于遇到的每个 text{‘)’}‘)’ ,我们从栈中弹出一个 text{‘(’}‘(’ ,如果栈顶没有 text{‘(’}‘(’,或者遍历完整个子字符串后栈中仍然有元素,那么该子字符串是无效的。这种方法中,我们对每个偶数长度的子字符串都进行判断,并保存目前为止找到的最长的有效子字符串的长度。

例子:
“((())”

(( --> 无效
(( --> 无效
() --> 有效,长度为 2
)) --> 无效
((()–> 无效
(())–> 有效,长度为 4
最长长度为 4

方法 2:动态规划
算法

这个问题可以通过动态规划解决。我们定义一个dp 数组,其中第 i 个元素表示以下标为 i 的字符结尾的最长有效子字符串的长度。我们将 dp 数组全部初始化为 0 。现在,很明显有效的子字符串一定以 ‘)’ 结尾。这进一步可以得出结论:以 ‘(’ 结尾的子字符串对应的 dp 数组位置上的值必定为 0 。所以说我们只需要更新 ‘)’ 在 dp 数组中对应位置的值。

为了求出 dp 数组,我们每两个字符检查一次,如果满足如下条件
在这里插入图片描述

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        if not s:
            return 0
        else:
            length = len(s)
            ans = [0]*length   # 注意这里的元素ans[i]的含义,是包括第i个字符的最长有效字符串的长度
            # 比如 “()())" 这里的 ans[4]=0
            for i in range(1, length):
                if s[i] == ')':
                    # 那么就往前找左括号去匹配
                    if s[i-1] == '(':
                        # ans[i] = ans[i-2]+2 卧槽,这里一定要注意,这里i=1不会出现数组越界的情况,
                        # 因为s[-1]指向最后一个字符,所以一定要小心
                        if i>=2:
                            ans[i]=ans[i-2]+2
                        else:
                            ans[i]=2
                    else:
                        if (i-ans[i-1]) >0 and s[i-ans[i-1]-1] == '(':
                            if i-ans[i-1]-1 >= 2:
                                ans[i] = ans[i-ans[i-1]-2]+ans[i-1]+2
                            else:
                                ans[i] = ans[i-1]+2
        return max(ans)

方法 4:不需要额外的空间
算法

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

接下来,我们从右到左做一遍类似的工作。

public class Solution {
    public int longestValidParentheses(String s) {
        int left = 0, right = 0, maxlength = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                left++;
            } else {
                right++;
            }
            if (left == right) {
                maxlength = Math.max(maxlength, 2 * right);
            } else if (right >= left) {
                left = right = 0;
            }
        }
        left = right = 0;
        for (int i = s.length() - 1; i >= 0; i--) {
            if (s.charAt(i) == '(') {
                left++;
            } else {
                right++;
            }
            if (left == right) {
                maxlength = Math.max(maxlength, 2 * left);
            } else if (left >= right) {
                left = right = 0;
            }
        }
        return maxlength;
    }
}

复杂度分析

时间复杂度: O(n)O(n) 。遍历两遍字符串。
空间复杂度: O(1)O(1) 。仅有两个额外的变量 leftleft 和 rightright 。

作者:LeetCode
链接:https://leetcode-cn.com/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

总结

这道题主要还是总结以下动态规划部分,动态规划的思考还是没有搞出来。看完题解觉得思路倒是不难,但是后面编码的时候,提交了好几次都不对。总是发现有错误,上面代码中注释也提及到了注意的问题所在。这道题还是可以重新多做几遍的。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/sakurasakura1996/article/details/104344270
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢