题目
有效括号字符串为空 ("")、"(" + A + ")" 或 A + B,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。例如,"","()","(())()" 和 "(()(()))" 都是有效的括号字符串。
如果有效字符串 S 非空,且不存在将其拆分为S=A+B
的方法,我们称其为原语(primitive),其中 A 和 B 都是非空有效括号字符串。
给出一个非空有效字符串 S,考虑将其进行原语化分解,使得:S = P_1 + P_2 + ... + P_k
,其中 P_i 是有效括号字符串原语。
对S进行原语化分解,删除分解中每个原语字符串的最外层括号,返回S。
示例1:
输入:"(()())(())"
输出:"()()()"
解释:输入字符串为 "(()())(())",原语化分解得到 "(()())" + "(())",删除每个部分中的最外层括号后得到 "()()" + "()" = "()()()"。
示例2:
输入:"(()())(())(()(()))"
输出:"()()()()(())"
解释:输入字符串为 "(()())(())(()(()))",原语化分解得到 "(()())" + "(())" + "(()(()))",删除每隔部分中的最外层括号后得到 "()()" + "()" + "()(())" = "()()()()(())"。
示例3:
输入:"()()"
输出:""
解释:输入字符串为 "()()",原语化分解得到 "()" + "()",删除每个部分中的最外层括号后得到 "" + "" = ""。
思路
因为S本身就是有效字符串,所以可以依据它的性质来解题。
方法1-使用计数方法:
使用两个变量分别记录左括号(L)和右括号(R)的个数,左括号初始为1,右括号初始为0。当遇见左括号L就加1,遇见右括号R就加1。当L等于R时,说明找到了一组P_i,重新初始化L与R,并继续遍历。L不等于R的情况,就将当前遍历到的字符加入结果变量中。
方法2-栈的使用:
- 如果是右括号,就将栈顶括号弹出;
- 如果栈不为空,就将当前元素加入结果变量中;
- 如果是左括号,就将其推入栈中。
解答
1.计数法:
class Solution {
public:
string removeOuterParentheses(string S) {
//因为S第一个字符一定是左括号,所以可以从1开始遍历,因此L=1
int L=1;int R=0;
string ans;
for(int i=1;i<S.size();i++){
if(S[i]=='(')L++;
else R++;
if(R!=L)
ans.push_back(S[i]);
else {
i++; //跳过第一个左括号
L=1;R=0; //初始化
}
}
return ans;
}
};
2.栈:
class Solution {
public:
string removeOuterParentheses(string S) {
string res;
stack<char> sta;
for (int i = 0; i < S.size(); i++) {
if (S[i] == ')')
sta.pop();
if (!sta.empty())
res.push_back(S[i]); //push_back速度比“+”运算快
if (S[i] == '(')
sta.push('(');
}
return res;
}
};
【关注公众号DoCode,每日一道LeetCode,将零碎时间利用起来】