Leetcode中括号题

想到括号问题,我最熟悉的是用stack来判断一个括号序列是否为valid。没错,这就是我对括号题,最初的认识。

题目一:Valid Parentheses

Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 

思路:利用栈存最近访问的括号,如果遇到右括号,则到了judge时候。

class Solution {
public:
    bool isValid(string s) {
        stack<char> brackets;
        int n=s.length();
        if(n==0) return true;
        if(n==1) return false;
        int i=0;
        for(i=0; i<n; i++){
            if(s[i]=='(' || s[i]=='{' || s[i]=='[')
                brackets.push(s[i]);
            if(s[i]==')'){
                if(brackets.empty()) return false;
                char top=brackets.top();
                brackets.pop();
                if(top!='(') return false;
            }
            if(s[i]=='}'){
                if(brackets.empty()) return false;
                char top=brackets.top();
                brackets.pop();
                if(top!='{') return false;
            }
            if(s[i]==']'){
                if(brackets.empty()) return false;
                char top=brackets.top();
                brackets.pop();
                if(top!='[') return false;
            }
        }
        if(brackets.empty()) return true;
        return false;
     }
};


题目二: Generate Parentheses

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

思路:这题的关键点是左括号数必须等于右括号数,另外任何时候右括号数不超过左括号数。

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> res;
        generateParenthesis(res, "", n, n, n, 0);
        return res;
    }
    
    void generateParenthesis(vector<string>& res, string s, int left, int right, int n, int lev){
        if(lev==n*2){
            res.push_back(s);
            return;
        }
        if(left) generateParenthesis(res, s+'(', left-1, right, n, lev+1);
        if(right>left && right) generateParenthesis(res, s+')', left, right-1, n, lev+1);
    }
};


前面两道都算是水题,下面这个题个人觉得比较难。需要动点脑筋。不是简单递归下或者stack遍历下就能解决的。


题目三:Longest Valid Parentheses

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

思路:我在这道题上犯二逼了,老是想着stack遍历,祈求能统计得到联系合理的括号对,但是老尝试失败,还折腾了一下午。。。后来,discussion里的小伙伴又拯救了我。从另一个思路出发,用stack存左括号,严格来说只存为匹配上的左括号(好像和stack遍历也没啥区别,到这里)。不同的是,这个stack不再是单纯存括号本身,而是存括号的index,可以通过index得到substring的长度(这应该是一种很普通的想法,可我咋就是没想到,猪~)

class Solution {
public:
    int longestValidParentheses(string s) {
        stack<int> pstack;  //栈存放unmatched左括号
        int n=s.length();
        if(n==0 || n==1) return 0;
        
        int maxcount=0;
        int lastofleft=0;
        for(int i=0; i<n; i++){
            if(s[i]=='(') pstack.push(i);  //保存左括号的索引
            else{
                if(!pstack.empty()){  
                    pstack.pop(); //求出上一个unmatched左括号到当前位置之前的括号个数
                    if(!pstack.empty())  //如果当前stack非空,则返回上一个左括号的位置
                        maxcount=max(maxcount, i-pstack.top());
                    else  //如果当前stack为空,则求lastofleft到i之间的段的括号个数
                        maxcount=max(maxcount, i-lastofleft+1);
                }
                else lastofleft=i+1; //如果是右括号而且stack为空,这开始新的计数
            }
        }
        return maxcount;
    }
};
这个思路应该很眼熟才对,没错,就是就是maximal rectangle area,都是利用堆栈,更重要的是都是substring


也有其他小伙伴提出一种DP的解决方法,个人觉得不算是很大众的解法。这里也贴出来。利用动态规划的思想,用一维数值dp[]保存i到s末尾最大有效括号的长度

class Solution {
public:
    int longestValidParentheses(string s) {
        //利用动态规划的思想,用一维数值dp[]保存i到s末尾最大有效括号的长度
        int n=s.length();
        vector<int> dp(n, 0);
        int maxcount=0;
        
        for(int i=n-2; i>=0; i--){  //倒序更新dp的值
            if(s[i]=='('){
                int j=i+1+dp[i+1];  //上个未匹配到的位置
                if(j<n && s[j]==')'){
                    dp[i]=dp[i+1]+2;
                    if(j+1<n)
                        dp[i]=dp[i]+dp[j+1];
                }
            }
            maxcount=max(maxcount, dp[i]);
        }
        return maxcount;
    }
};


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值