验证括号是否匹配,能够用*替换 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;     } }

相关文章
相关标签/搜索