问题:函数
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
'('
must have a corresponding right parenthesis ')'
.')'
must have a corresponding left parenthesis '('
.'('
must go before the corresponding right parenthesis ')'
.'*'
could be treated as a single right parenthesis ')'
or a single left parenthesis '('
or an empty string.Example 1:spa
Input: "()" Output: True
Example 2:code
Input: "(*)" Output: True
Example 3:递归
Input: "(*))" Output: True
Note:three
解决:字符串
① 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; } }