给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
任何左括号 ( 必须有相应的右括号 )。
任何右括号 ) 必须有相应的左括号 ( 。
左括号 ( 必须在对应的右括号之前 )。
* 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
一个空字符串也被视为有效字符串。
示例 1:
输入: "()"
输出: True
示例 2:
输入: "(*)"
输出: True
示例 3:
输入: "(*))"
输出: True
注意:
字符串大小将在 [1,100] 范围内。
思路:用栈模拟,如果字符中只有左右括号的话就是个sb题,但是多了个‘*’,此时我们就多了很多能够合法的情况,我的方法比较巧妙,是突然想到的,我们可以在栈中存还没匹配的左括号的位置,这样能够一举两得,不仅能够说明当前有没有左括号还没匹配,而且能够用来判定最后剩下的左括号还能和那些‘*’进行消除! 除此之外,我开了一个sum数组,标记‘*’的前缀和,这个前缀和并不是一成不变的,因为它很有可能在遍历过程中和有括号进行匹配。复杂度是线性的哈哈哈
class Solution {
public boolean checkValidString(String s) {
int[] sum=new int[s.length()];
Stack<Integer> st=new Stack<>();
for(int i=0;i<s.length();i++) {
if(s.charAt(i)=='*') sum[i]=1;
if(i>0) sum[i]+=sum[i-1];
if(s.charAt(i)=='(')
st.add(i);
else if(s.charAt(i)==')'){
if(st.isEmpty()) {
if(sum[i]>0) sum[i]--;
else return false;
}
else st.pop();
}
}
while(!st.isEmpty()) {
if(sum[s.length()-1]-sum[st.peek()]>0) {
sum[s.length()-1]--;
st.pop();
}
else
return false;
}
return true;
}
}