13 力扣热题刷题记录之第32题最长有效括号

系列文章目录

力扣刷题记录

前言

真的要每天进步一点点呀!!

一、背景

给出字符串,找到最长有效括号。
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

来源:力扣
链接: https://leetcode-cn.com/problems/longest-valid-parentheses/

二、我的思路

一开始我的思路很简单,用栈呗,当栈顶元素是‘(’的时候,进来的是‘)’,那么就出栈栈顶元素,一直看最后栈内剩余的元素有多少。我私以为总个数减去剩余个数,便是最后的有效括号数。

但是,我忽略了当串中间有括号未能被匹配的时候,也是会留在栈里面,所以求得的并不是最长有效括号。这也是为什么我加粗了最长的原因。

思来想去,没啥子办法,耗了一晚上。最后看了一点题解,艾,可以用动态规划呀!!!

当有匹配的括号,就在右括号对应的下标进行+2,左括号就默认为前一个值如“(())”。但是这样忽略一个问题,就是这样“()(()”,中间那个左括号等于前一个的值的话,岂不是最后有效长度为4了,这不对。

于是乎,怎么解决呢?不妨让左括号下标对应的数组值为0。但是遇到的情况是:“()()”,这样有效输出是2,这明显不对啊。

于是考虑解决。很明显,左括号下标的数组值必须为0,这是在前面验证过的,那我们可以在匹配到右括号的时候,判断当前配对括号的前一个数组值是否为0,不为零,那么应该加上前面的。

这样就合理了。来操作一下代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        stack<char> my_stack;
        int vec[30000]={0};//栈当数组
        int max_i=0;
        int i=0;
        for(char c:s)
        {
            if(c=='(') {
                my_stack.push(c);
                vec[i]=0;//左括号等于0
            }
            else 
            {
                if (!my_stack.empty()&&my_stack.top()=='(' )   
                {
                    my_stack.pop();
                    if(i>0) 
                        vec[i]=vec[i-1]+2; //有括号且配对,则在前一个加2
                    if(i-vec[i]>=0&&vec[i-vec[i]]!=0)
                        vec[i]+=vec[i-vec[i]];
                }
                else
                {
                    //如右括号不配对
                    my_stack.push(c);
                    int mid=-1;
                    if(i>0)
                        mid=i-1-vec[i-1];//记录前一个匹配之前的一个下标
                    else vec[i]=0;
                    if(mid>=0&&s[mid]=='(') //如果它符合(())这样,加上i前一个i-1的数组值
                    {
                        vec[i]=vec[i-1]+2;
                        //如果是这样()(()),
                        //那么还要加上(())之前的数值
                        if(mid-1>=0&&vec[mid-1]!=0)
                            vec[i]+=vec[mid-1];
                    }     
                    else vec[i]=0;
                }        
            } 
            max_i=max(max_i,vec[i]);
            i++;
            
        }
        return max_i;
    }
};

运行通过,唉。

其实最后发现栈其实没必要的,直接用下标操作即可。

三、官方的思路

官方可太强了,三个思路。

1.动态规划

这思路,我是抄它的,它的代码是真的精简啊,直接来代码!!

class Solution {
public:
    int longestValidParentheses(string s) {
        int maxans = 0, n = s.length();
        vector<int> dp(n, 0);
        for (int i = 1; i < n; i++) {
            if (s[i] == ')') {
                if (s[i - 1] == '(') {
                    dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
                } else if (i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '(') {
                    dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;
                }
                maxans = max(maxans, dp[i]);
            }
        }
        return maxans;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode-solution/
来源:力扣(LeetCode)

2.用栈

这个办法巧妙在于,栈不是用来存放括号,而是用来存放括号的下标。当遇到右括号匹配,出栈,开始计算有效括号长度,最长长度。办法是:用当前下标,减去栈顶元素下标。如果遇到右括号,且栈为空,直接存放右括号下标进去。

这样会有一种情况,刚开始如果没有右括号,这个时候一直来有效括号,那么栈顶就没有元素了呀,这个时候,就统一提前放一个-1的元素,当有孤独的右括号时,把这个-1扔出去即可。

代码如下:

class Solution {
public:
    int longestValidParentheses(string s) {
        int maxans = 0;
        stack<int> stk;
        stk.push(-1);
        for (int i = 0; i < s.length(); i++) {
            if (s[i] == '(') {
                stk.push(i);
            } else {
                stk.pop();
                if (stk.empty()) {
                    stk.push(i);
                } else {
                    maxans = max(maxans, i - stk.top());
                }
            }
        }
        return maxans;
    }
};


作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode-solution/
来源:力扣(LeetCode)

3.左右括号记数

这个办法简直太巧妙了,以至于我都不知道怎么想出来的。

同时统计左右括号数量,当数量相等时,开始计算,如果右括号数大于左边,则归0,但是遇到这样的就没办法了:()(()。左右不相等,右也不大于左,那咋办。

从另一边开始遍历试试,同时判断条件也反过来,我去,真的解决了,牛逼!!

代码如下:

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



作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode-solution/
来源:力扣(LeetCode)

总结

不懂就别死磕,先看提示,一步步递进,最后再看人家的解决办法!!!

毕竟,很多算法并不是我们想出来的,只要会用就可以了,如果我们对自己没有那么高的要求的话。

喜欢就点个赞叭!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值