leetcode:678. 有效的括号字符串
题目
给定一个只包含三种字符的字符串:(,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
- 任何左括号
(必须有相应的右括号)。 - 任何右括号
)必须有相应的左括号(。 - 左括号
(必须在对应的右括号之前)。 *可以被视为单个右括号),或单个左括号(,或一个空字符串。- 一个空字符串也被视为有效字符串。
示例:
输入: "()"输出: True
输入: "(*)"输出: True
输入: "(*))"输出: True
解答 & 代码
解法 0:递归回溯(超时)
class Solution {private:bool backTrace(string s, int idx, int leftCnt, int rightCnt){// 递归结束条件 1:字符串遍历结束,返回左括号数是否等于右括号数if(idx == s.size())return leftCnt == rightCnt;// 如果之前已遍历的字符串中的右括号数 > 左括号数,肯定不合法,返回 falseif(rightCnt > leftCnt)return false;// 如果当前是左括号if(s[idx] == '(')return backTrace(s, idx + 1, leftCnt + 1, rightCnt);// 如果当前是右括号else if(s[idx] == ')')return backTrace(s, idx + 1, leftCnt, rightCnt + 1);// 如果当前是星号else if(s[idx] == '*')return backTrace(s, idx + 1, leftCnt + 1, rightCnt) ||backTrace(s, idx + 1, leftCnt, rightCnt + 1) ||backTrace(s, idx + 1, leftCnt, rightCnt);elsereturn false;}public:bool checkValidString(string s) {return backTrace(s, 0, 0, 0);}};
解法二:栈
[简单] 20. 有效的括号
类似上面这道题,只是多了星号要处理
左括号栈 + 星号栈(两个栈都存储对应的下标)
- 遍历字符串
- 如果当前是左括号,则将当前下标存入左括号栈
- 如果当前是星号,则将当前下标存入星号栈
- 如果当前是右括号
- 优先和左括号匹配,及如果左括号栈不为空,则弹出左括号栈栈顶元素
- 若左括号栈为空,则和星号匹配(将星号当作左括号)。如果星号栈不为空,则弹出星号栈栈顶
- 如果两个栈都为空,则无法匹配,直接返回
false
- 匹配剩余左括号,即如果左括号栈不为空,则将星号当作右括号,和左括号栈中的剩余左括号匹配
- 如果星号栈为空,则无法匹配,直接返回
false - 如果星号栈栈顶下标小于左括号栈栈顶下标,则无法匹配,直接返回
false - 否则,能够匹配,弹出两个栈栈顶元素
- 如果星号栈为空,则无法匹配,直接返回
最后左括号栈为空,返回
true(不论星号栈是否为空,若星号栈还有元素,则剩余星号当作空字符即可)class Solution {public:bool checkValidString(string s) {stack<int> leftS; // 存储左括号对应下标的栈stack<int> starS; // 存储星号对应下标的栈// 1. 遍历字符串for(int i = 0; i < s.size(); ++i){// 1.1 如果当前是左括号,则将当前下标存入左括号栈if(s[i] == '(')leftS.push(i);// 1.2 如果当前是星号,则将当前下标存入星号栈else if(s[i] == '*')starS.push(i);// 1.3 如果当前是右括号else if(s[i] == ')'){// a. 优先和左括号匹配,及如果左括号栈不为空,则弹出左括号栈栈顶元素if(!leftS.empty())leftS.pop();// b. 若左括号栈为空,则和星号匹配(将星号当作左括号)// 如果星号栈不为空,则弹出星号栈栈顶else if(!starS.empty())starS.pop();// c. 如果两个栈都为空,则无法匹配,直接返回 falseelsereturn false;}}// 2. 将星号当作右括号,和左括号栈中的剩余左括号匹配while(!leftS.empty()){// 如果左括号栈不为空,而星号栈为空 or 星号栈栈顶下标小于左括号栈栈顶下标// 则无法匹配,直接返回 fasleif(starS.empty() || starS.top() < leftS.top())return false;// 否则,能够匹配,弹出两个栈栈顶leftS.pop();starS.pop();}// 3. 最后左括号栈为空,返回 truereturn true;}};
复杂度分析:设字符串
s长为 N
- 时间复杂度 O(N):
- 空间复杂度 O(N):
执行结果:
执行结果:通过执行用时:0 ms, 在所有 C++ 提交中击败了 100.00% 的用户内存消耗:6 MB, 在所有 C++ 提交中击败了 68.67% 的用户
