驗證括號是否匹配,能夠用*替換 Valid Parenthesis String

問題:函數

Given a string containing only three types of characters: '(', ')' and '*', write a function to check whether this string is valid. We define the validity of a string by these rules:this

  1. Any left parenthesis '(' must have a corresponding right parenthesis ')'.
  2. Any right parenthesis ')' must have a corresponding left parenthesis '('.
  3. Left parenthesis '(' must go before the corresponding right parenthesis ')'.
  4. '*' could be treated as a single right parenthesis ')' or a single left parenthesis '(' or an empty string.
  5. An empty string is also valid.

Example 1:spa

Input: "()"
Output: True

Example 2:code

Input: "(*)"
Output: True

Example 3:遞歸

Input: "(*))"
Output: True

Note:three

  1. The string size will be in the range [1, 100].

解決:字符串

① string

使用兩個stack,分別存放左括號和星號的位置it

遍歷字符串,當遇到星號時,壓入星號棧star,當遇到左括號時,壓入左括號棧left,當遇到右括號時,此時若是left和star均爲空時,直接返回false;若是left不爲空,則pop一個左括號來抵消當前的右括號;不然從star中取出一個星號看成左括號來抵消右括號。io

當循環結束後,咱們但願left中沒有多餘的左括號,就算有,咱們能夠嘗試着用星號來抵消,當star和left均不爲空時,進行循環,若是left的棧頂左括號的位置在star的棧頂星號的右邊,那麼就組成了 *( 模式,直接返回false;不然就說明星號能夠抵消左括號,各自pop一個元素。最終退出循環後咱們看left中是否還有多餘的左括號,沒有就返回true,不然false。

class Solution { //6ms
    public boolean checkValidString(String s) {
        Stack<Integer> left = new Stack<>();
        Stack<Integer> star = new Stack<>();
        char[] schar = s.toCharArray();
        for (int i = 0;i < schar.length;i ++){
            if (schar[i] == '*'){
                star.push(i);
            }else if (schar[i] == '('){
                left.push(i);
            }else {
                if (left.isEmpty() && star.isEmpty()){
                    return false;
                }
                if (! left.isEmpty()){
                    left.pop();
                }else {
                    star.pop();
                }
            }
        }
        while (! left.isEmpty() && ! star.isEmpty()){
            if (left.peek() > star.peek()){
                return false;
            }
            left.pop();
            star.pop();
        }
        return left.isEmpty();
    }
}

② dfs,使用了變量count來記錄左括號的個數,變量start表示當前開始遍歷的位置,那麼在遞歸函數中:

首先判斷若是count小於0,直接返回false。不然進行從start開始的遍歷,若是當前字符爲左括號,count自增1;若是爲右括號,若count此時小於等於0,返回false,不然count自減1;

若是爲星號,咱們同時遞歸三種狀況,分別是當星號爲空,左括號,或右括號,只要有一種狀況返回true,那麼就是true了。若是循環退出後,若count爲0,返回true,不然false。

class Solution { //341ms
    public boolean checkValidString(String s) {
        return dfs(s,0,0);
    }
    public boolean dfs(String s,int start,int count){
        if (count < 0) return false;
        for (int i = start;i < s.length();i ++){
            if (s.charAt(i) == '('){
                count ++;
            }else if (s.charAt(i) == ')'){
                if (count <= 0) return false;
                count --;
            }else {
                return dfs(s,i + 1,count) || dfs(s,i + 1,count + 1) || dfs(s,i + 1,count - 1);
            }
        }
        return count == 0;
    }
}

③ 維護了兩個變量low和high,其中low表示在有左括號的狀況下,將星號看成右括號時左括號的個數(這樣作的緣由是儘可能很少增長右括號的個數),而high表示將星號看成左括號時左括號的個數

當high小於0時,說明就算把星號都看成左括號了,仍是不夠抵消右括號,返回false。而當low大於0時,說明左括號的個數太多了,沒有足夠多的右括號來抵消,返回false。

那麼開始遍歷字符串,當遇到左括號時,low和high都自增1;當遇到右括號時,只有當low大於0時,low才自減1,保證了low不會小於0,而high直接自減1;

當遇到星號時,只有當low大於0時,low才自減1,保證了low不會小於0,而high直接自增1,由於high把星號看成左括號。當此時high小於0,說明右括號太多,返回false。當循環退出後,咱們看low是否爲0。

class Solution { //5ms     public boolean checkValidString(String s) {         int low = 0;         int high = 0;         for (char c : s.toCharArray()){             if (c == '('){                 low ++;                 high ++;             }else if (c == ')'){                 if (low > 0) low --;                 high --;             }else{                 if (low > 0) low --;                 high ++;             }             if (high < 0) return false;         }         return low == 0;     } }

相關文章
相關標籤/搜索