有效括号字符串为空""、"("+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:
输入:s = “(()())(())”
输出:”()()()”
解释:
输入字符串为 “(()())(())”,原语化分解 得到”(()())” + “(())”,
删除每个部分中的最外层括号得到”()()” + “()” = “()()()”
示例2:
输入:s = “(()())(())(()(()))”
输出:”()()()()(())”
解释:
输入字符串为 “(()())(())(()(()))”,原语化分解得到 “(()())” + “(())” + “(()(()))”,
删除每个部分中的最外层括号后得到 “()()” + “()” + “()(())” = “()()()()(())”。
示例3:
输入:s = “()()”
输出:””
解释:
输入字符串为 “()()”,原语化分解得到 “()” + “()”,
删除每个部分中的最外层括号后得到 “” + “” = “”。
提示:
1 <= s.length <= 105s[i]为'('或')'s是一个有效括号字符串
计数:
从 ss 开始位置计算子数组的和,遇到 ‘(’ 则加 1,遇到‘)’ 则减 1,第一次和为 0 时则为第一个原语。从上一个原语的结束位置的下一个位置开始继续求子数组的和,和首次为 0 时则是另一个新的原语,直到遇到 s 的结尾。保存结果时,忽略每个原语的开始字符和结尾字符,其他字符均保存下来生成新的字符串。代码对流程进行了部分优化,减少了判断语句。
class Solution {public String removeOuterParentheses(String S) {StringBuilder sb = new StringBuilder();int level = 0;for (char c : S.toCharArray()) {if (c == ')') --level;if (level >= 1) sb.append(c);if (c == '(') ++level;}return sb.toString();}}
栈:
遍历 s,并用一个栈来表示括号的深度。遇到‘(’ 则将字符入栈,遇到‘)’ 则将栈顶字符出栈。栈从空到下一次空的过程,则是扫描了一个原语的过程。一个原语中,首字符和尾字符应该舍去,其他字符需放入结果字符串中。因此,在遇到 ‘(’ 并将字符入栈后,如果栈的深度为 1,则不把字符放入结果;在遇到‘)’ 并将栈顶字符出栈后,如果栈为空,则不把字符放入结果。其他情况下,需要把字符放入结果。代码对流程进行了部分优化,减少了判断语句。
class Solution {public String removeOuterParentheses(String s) {StringBuilder res = new StringBuilder();Deque<Character> stack = new ArrayDeque<>();for (char c : s.toCharArray()) {if (c == ')') stack.pop();if (!stack.isEmpty()) res.append(c);if (c == '(') stack.push(c);}return res.toString();}}
