問題:函數
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; } }