题目:
给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
任何左括号 ( 必须有相应的右括号 )。
任何右括号 ) 必须有相应的左括号 ( 。
左括号 ( 必须在对应的右括号之前 )。
- 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
一个空字符串也被视为有效字符串。
示例 1:
输入: “()”
输出: True
示例 2:
输入: “(*)”
输出: True
示例 3:
输入: “(*))”
输出: True
注意:
字符串大小将在 [1,100] 范围内。
解答:
我用的方法是栈。
刚开始的思路:左括号和下标小于长度一半的星号入栈,右括号和其他星号则当做右括号,操作完成后如果栈的长度为0或1,则返回true,此思路能通过69/83.
class Solution {
public:
bool checkValidString(string s) {
int len = s.length();
cout<<len;
stack<char> sta;
for(int i = 0;i<len;i++){
if(s[i]=='('||(s[i]=='*'&&i<len/2)){ //左括号和下标小于长度一半的星号入栈,右括号和其他星号则当做右括号,操作完成后如果栈的长度为0或1,则返回true,此思路能通过69/83.
//不能通过的情况为"(((()*())))((()(((()(()))()**(*)())))())()()*",原因是当操作到一定位置后,此时字符串还未遍历的")())()()*"一看就会返回false,但实际为true.
sta.push(s[i]);
}
else{
if(sta.empty()){
sta.push(s[i]);
}
else{
sta.pop();
}
}
}
if(sta.size()==1&&len==1&&s[0]=='(') return false;
if(sta.size()>1) return false;
return true;
}
};
不能通过的情况为"(((()*())))((()(((()(()))()**(*)())))())()()*",原因是当操作到一定位置后,此时字符串还未遍历的")())()()*"一看就会返回false,但实际为true.
但是还没啥解决办法,于是转而用两个栈。分别存储左括号和星号。从左到右遍历字符串,进行如下操作:
- 如果遇到左括号,则将当前下标存入左括号栈。
- 如果遇到星号,则将当前下标存入星号栈。
- 如果遇到右括号,则需要有一个左括号或星号和右括号匹配,由于星号也可以看成右括号或者空字符串,因此当前的右括号应优先和左括号匹配,没有左括号时和星号匹配:
- 如果左括号栈不为空,则从左括号栈弹出栈顶元素;
- 如果左括号栈为空且星号栈不为空,则从星号栈弹出栈顶元素;
- 如果左括号栈和星号栈都为空,则没有字符可以和当前的右括号匹配,返回 false。
遍历结束之后,左括号栈和星号栈可能还有元素。为了将每个左括号匹配,需要将星号看成右括号,且每个左括号必须出现在其匹配的星号之前。当两个栈都不为空时,每次从左括号栈和星号栈分别弹出栈顶元素,对应左括号下标和星号下标,判断是否可以匹配,匹配的条件是左括号下标小于星号下标,如果左括号下标大于星号下标则返回false。
最终判断左括号栈是否为空。如果左括号栈为空,则左括号全部匹配完毕,剩下的星号都可以看成空字符串,此时 s 是有效的括号字符串,返回 true。如果左括号栈不为空,则还有左括号无法匹配,此时 s 不是有效的括号字符串,返回false。
class Solution {
public:
bool checkValidString(string s) {
int len = s.length();
stack<char> sta1;//左括号栈
stack<char> sta2;//星号栈
for(int i = 0;i<len;i++){
if(s[i]=='('){
sta1.push(i);
}
else if(s[i]=='*'){
sta2.push(i);
}
else{
if(!sta1.empty()){
sta1.pop();
}
else if(sta1.empty()&&!sta2.empty()){
sta2.pop();
}
else{
return false;
}
}
}
cout<<sta1.size()<<" "<<sta2.size();
if(sta1.size()==1&&len==1&&s[0]=='(') return false;
if(sta2.size()<sta1.size()) return false;//剩的星号比左括号少,肯定false
else{
while(!sta1.empty()){
if(sta1.top()<=sta2.top()){
sta1.pop();
sta2.pop();
}
else return false;
}
}
return true;
}
};