leetcode32. 最长有效括号

换换口味做一下leetcode的题
最最普通的版本,时间和内存消耗都相对比较大。从头到尾扫描vector,合并相邻或中间隔着成对括号的左和右,当vector长度不变时计算所有标记成对的节点的数目,即最长子串。

class Solution {
public:
    struct Node{
        int state=0;//0为成对,-1为左,1为右
        int num=0;
    };
    int longestValidParentheses(string s) {
        vector<Node> v;
        int maxlen=0,currlen=0;
        if(strlen(s.c_str())==0)return 0;
        for(int i=0;i<strlen(s.c_str());i++){
            int flag=1;
            if(s[i]=='(') flag=-1;

            if(v.empty() || v.back().state!=flag){
                Node node;
                node.state=flag;
                node.num=1;
                v.push_back(node);
            }else v.back().num++;
        }
        int oldsize=-1;
        while(v.size()!=oldsize){
            oldsize=v.size();
            //合并
            for(int i=0;i<v.size()-1;/*i++*/){
                if(v[i].state==-1 && v[i+1].state==1){
                    int minnum=min(v[i].num,v[i+1].num);
                    v[i].num-=minnum;
                    v[i+1].num-=minnum;
                    Node temp;
                    temp.state=0;
                    temp.num=2*minnum;
                    v.insert(v.begin()+1+i,temp);
                    //it++;
                }else if(i<v.size()-2 && v[i].state==-1 && v[i+1].state==0 && v[i+2].state==1){
                    int minnum=min(v[i].num,v[i+2].num);
                    v[i].num-=minnum;
                    v[i+2].num-=minnum;
                    v[i+1].num+=2*minnum;
                    i++;
                }else i++;
            }
            //合并成对 删除0
            for(vector<Node>::iterator it=v.begin();it!=v.end();){
                if(it->num==0){
                    it=v.erase(it);
                }else it++;
            }
            for(int i=0;i<v.size()-1;i++){
                if(v[i].state==v[i+1].state){
                    v[i].num+=v[i+1].num;
                    v.erase(v.begin()+i+1);
                }
            }
        }
        for(vector<Node>::iterator it=v.begin();it!=v.end();it++){
            if(it->state==0 && it->num > maxlen){
                maxlen=it->num;
            }
        }
        return maxlen;
    }
};

还有一个计数的版本,时间消耗还是比较大,可能是因为string的reverse(吧),用lastend来记录上一个闭合括号的结束位置,判断两个闭合括号是否相连。右闭合的判定比较复杂,此处不做处理,reverse之后再互换,相当于对原串从右到左再扫一遍。因为是对称的,最后取最大值。

class Solution {
public:
    int cnt(string s){
        int maxlen=0,currlen=0,lastend=0;
        int left=0,right=0;
        bool state=false;
        for(int i=0;i<strlen(s.c_str());i++){
            if(s[i]=='(')state=true;//左括号是表达式开始
            if(!state)continue;
            if(s[i]=='(') left++;
            else right++;

            if(right==left){
                if(i-2*left==lastend)currlen+=left*2;
                else currlen=left*2;
                lastend=i;
                left=right=0;
                state=false;
            }
            maxlen=max(maxlen,currlen);
        }
        return maxlen;
    }; 
    int longestValidParentheses(string s) {
        int maxlen1=0,maxlen2=0;
        maxlen1=cnt(s);
        reverse(s.begin(),s.end());
        for(int i=0;i<strlen(s.c_str());i++){
            if(s[i]=='(')s[i]=')';
            else s[i]='(';
        }
            maxlen2=cnt(s);
        return max(maxlen1,maxlen2);
    }
};

还可以用栈做,就先不写惹

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值