zoukankan      html  css  js  c++  java
  • 括号相关算法


    括号相关的大多数用栈和dp,或者左右各自遍历一遍

    lt20 合法括号

    用栈,遍历string,左半边则入栈,右边则检查栈是否空和栈顶是否匹配。

    • c++
    vector<char>str;
        bool isValid(string s) {
            for(int i=0;i<s.size();i++)
            {
                if(s[i]=='('||s[i]=='{'||s[i]=='[')
                   str.push_back(s[i]);
                else{
                    if(!str.empty()&&str.back()==get(s[i]))
                    {
                        str.pop_back();
                    }else{
                        return false;
                    }
                }
            }
            return str.size()==0;
        }
        char get(char x)
        {
            if(x=='}')
            return '{';
            else if(x==')')
            return '(';
            else
            return '[';
        }
    
    • golang 版本
    func isValid(s string) bool {
        //左边入栈,遇到右边判断,最后栈空则true
        stack:=make([]byte,0)
        for i:=0;i<len(s);i++{
            if s[i]=='('||s[i]=='['||s[i]=='{'{
                stack = append(stack,s[i])
            }else{
               if len(stack)!=0&&stack[len(stack)-1]==getChar(s[i]){
                   stack = stack[:len(stack)-1]
               }else{
                   return false
               }
            }
        }
        return len(stack)==0
    }
    //获取对应字符
    func getChar(str byte)byte{
        if str==')'{
            return '('
        }else if str ==']'{
            return '['
        }else{
            return '{'
        }
    }
    

    22 括号生成

    • dfs,左括号数量小于右括号有效
    func generateParenthesis(n int) []string {
        res:=make([]string,0)
        var dfs func(left int,right int,path string)
        dfs = func(left int,right int,path string){
            if n*2==len(path){
                res = append(res,path)
                return 
            }
    
            if left>0{ //左边括号数还存在,则增加
                dfs(left-1,right,path+"(")
            }
    
            if left<right{//右括号数量剩余多,则放置右括号
                dfs(left,right-1,path+")")
            }
        }
    
        dfs(n,n,"")
        return res
    }
    

    32 最长有效括号

    求最长有效括号,三种方法,栈,dp,左右遍历

    
    func longestValidParentheses(s string) int {
        //栈放置下标,遇到)且无(匹配则重新计数
        stack:=make([]int,0)
        stack = append(stack,-1)//先1放置-1
        res:=0
        for i:=0;i<len(s);i++{
            if s[i]=='('{
                stack = append(stack,i)
            }else{
                stack = stack[:len(stack)-1] //连续两个),第二个)会弹出第一个),然后stack空,第二个)位置的index入栈
                if len(stack)==0{ //没有和)匹配,入栈作为下次计算的初始
                    stack = append(stack,i)
                }else{
                    res = max(res,i-stack[len(stack)-1])
                }
            }
        }
        return res
    }   
    func max(x,y int)int{
        if x>y{
            return x
        }else{
            return y
        }
    }
    
    • dp,考虑多种情况,略复杂 O(n) O(n)
    func longestValidParentheses(s string) int {
       //dp 考虑多种情况
       dp:=make([]int,len(s))  //dp[i] 代表到i结尾字符串最长有效括号长度
       res:=0
       for i:=1;i<len(s);i++{ //s[i]=='(' 无匹配直接省略  从1开始,第0位'('或者')'都是无匹配
           if s[i]==')'{
               if i-1>=0&&s[i-1]=='('{
                   if i-2>=0{
                       dp[i] = dp[i-2]+2
                   }else{
                       dp[i] = 2
                   }
               }else if i-dp[i-1]-1>=0&&s[i-dp[i-1]-1]=='('{  //((...))情况
                   if i-dp[i-1]-2>=0{
                        dp[i] = dp[i-dp[i-1]-2]+dp[i-1]+2  // ()((...))情况
                   }else{
                       dp[i] = dp[i-1]+2
                   }
               }
           }  
           res  = max(res,dp[i])
       }
       return res
    }
    func max(x,y int)int{
       if x>y{
           return x
       }else{
           return y
       }
    }
    
    • 贪心,左右各一遍
    func longestValidParentheses(s string) int {
        //贪心,左右各自来一次
        res:=0
        left,right:=0,0
        for i:=0;i<len(s);i++{
            if s[i]=='('{
                left++
            }else{
                right++
            }
            if left==right{
                res = max(res,2*left)
            }else if right>left{
                left,right = 0,0
            }
        }
        left,right = 0,0
        //从右向左
        for i:=len(s)-1;i>=0;i--{
            if s[i]=='('{
                left++
            }else{
                right++
            }
    
            //左比右多则left,right归零
            if left==right{
                res = max(res,2*left)
            }else if left>right{
                left,right=0,0
            }
        }
        return res
    }
    func max(x,y int)int{
        if x>y{
            return x
        }else{
            return y
        }
    }
    

    678有效的括号字符串

    可以当(,),或者空串

    • 栈 O(n) O(n)
    func checkValidString(s string) bool {
        //双栈存储(和* ,遇到)优先匹配(,最后处理*空串
        left,star:=make([]int,0),make([]int,0)
        for i:=0;i<len(s);i++{
            if s[i]=='('{
                left = append(left,i)
            }else if s[i]=='*'{
                star = append(star,i)
            }else{
                if len(left)!=0{
                    left =left[:len(left)-1] //优先匹配(
                }else if len(star)!=0{
                    star = star[:len(star)-1]
                }else{
                    return false   //没有对应的匹配直接返回
                }
            }   
        }
    
        //结束如果(存在*存在继续把*当作)匹配,多余的*当作空串
        for len(left)!=0&&len(star)!=0{
            if left[len(left)-1]>star[len(star)-1]{  //(在*右边,不符合
                return false
            }
            left = left[:len(left)-1]
            star = star[:len(star)-1]
        }
    
        //最后如果(没有对应匹配则不符合
        return len(left)==0
    }
    
  • 相关阅读:
    vijos1776:关押罪犯
    vijos1774:机器翻译
    vijos1775:乌龟棋
    vijos1792:摆花
    vijos1100:加分二叉树
    vijos1706:舞会
    单调栈
    bzoj1677:求和
    bzoj1340: [Baltic2007]Escape逃跑问题
    bzoj4716: 假摔
  • 原文地址:https://www.cnblogs.com/9527s/p/14615397.html
Copyright © 2011-2022 走看看