678. 有效的括号字符串
上过数据结构课的最直观的印象,括号匹配用栈来存储
这个题目的变化就是增加了一个*
,可以代替左右括号或者视为空,依然可以用栈来解题,设置左括号和星号的栈,保存二者在字符串s中的位置,当遇到右括号时,优先pop左括号栈,左括号栈为空再pop星号栈,如果都空则false,最后通过左括号栈和星号栈中存的位置来判断星号和左括号是否可以匹配
class Solution {
public:
bool checkValidString(string s) {
stack<int> leftStack, starStack;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '(') {
leftStack.push(i);
} else if (s[i] == '*') {
starStack.push(i);
} else if (s[i] == ')') {
if (!leftStack.empty()) {
leftStack.pop();
} else if (!starStack.empty()) {
starStack.pop();
} else {
return false;
}
}
}
while (!leftStack.empty() && !starStack.empty()) {
if (leftStack.top() > starStack.top())return false;
leftStack.pop();
starStack.pop();
}
return leftStack.empty();
}
};
这种做法的时间复杂度达到了O(n)但是由于使用了额外的数据结构,空间复杂度也达到了O(n)
但是实际上并不需要维护左括号和星号的位置,只需要保证在左括号和右括号满足条件后左括号和星号也满足就可以了
遇到左括号,左括号数量加一
遇到右括号,左括号数量减一
遇到星号,则可能作为左括号也可能作为右括号,也可能忽略,也就是说左括号的数量加一减一或者不变,那么我们可以维护左括号的数量的范围leftMax和leftMin
在遍历s的过程中,如果左括号的最大数量比零要小,那么一定无法匹配,直接false
遍历结束,如果左括号的最小数量为零,说明可以匹配
class Solution {
public:
bool checkValidString(string s) {
int leftMax = 0, leftMin = 0;
for (char i : s) {
if (i == '(') {
leftMax++;
leftMin++;
} else if (i == '*') {
leftMax++;
leftMin = max(0, leftMin - 1);
} else if (i == ')') {
leftMax--;
leftMin = max(0, leftMin - 1);
if (leftMax < 0) { //
return false;
}
}
}
return leftMin == 0;
}
};