【LeetCode】32.最长有效括号

89 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

题目

给你一个只包含 '('')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1

输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"

示例 2

输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"

示例 3

输入:s = ""
输出:0

提示

  • 0 <= s.length <= 3 * 104
  • s[i]'('')'

题解

思路

在括号匹配问题当中,栈是非常通用、经典的解法。在这道题目中,用栈来做并不那么显然。但栈的方法比起动态规划之类的还是更加方便。

从左向右遍历,遇到'(',就把下标放到栈里。

(把下标放进去怎么用呢?因为本题只有'('')'两个元素,')'又不入栈,栈里只有一种元素,所以只有下标可以记录啦)

如果遇上')',说明一对括号已经匹配完成了。那么我们记录一次合法的子串长度。末端肯定是当前的下标,但起始端呢?

如果以当前栈顶的元素,即被匹配的'('作为起始段,那之前已经匹配完成的括号对就无法计入了,比如数据"(()()()"。

所以,在将当前的栈顶元素弹出栈后,选择现在的[栈顶元素+1]作为起始端(也就是正在等待匹配的'(')。这样,就可以囊括所有的已经匹配完成的括号对。

那如果在这之中,有不合法的括号怎么办?不合法的括号,一定是')'。为什么会不合法?因为当遍历到')'时,。没有响应的'('与之匹配,即栈为空。所以我们如果选择栈顶元素+1作为起始端,不会出现该处恰好为')'、包含不合法子串的现象。

那如果说弹出'('后,栈为空,以什么为起始呢?如果弹完后空栈,说明当前遍历到的所有括号都已完成匹配,没有多余的'('。那起始端就是上一个[不合法的')'+1]。所以遇到这种不合法的情况时,我们需要记录一下。栈非空的情况,stack[len]+1是起始端,那么为了方便,但栈空的时候len=0,我们将上一个不合法下标记录在stack[0]中。

当没出现过不合法情况时,即从s[0]开始都是合法的,那么stack[0]就初始化为0的前一位,即-1。

代码

class Solution {
public:
    int longestValidParentheses(string s) {
        int ans=0;
        int stack[30005];
        int len=0;
        stack[0]=-1;
        for(int i=0;i<s.length();i++){
            if(s[i]=='('){
                stack[++len]=i;
            }else{
                if(len){
                    len--;
                    ans=max(ans,i-stack[len]);
                }else stack[0]=i;
            }
        }
        return ans;
    }
};

结语

业精于勤,荒于嬉;行成于思,毁于随。