题目
(1)有效括号字符串为空 “”、"(" + A + “)” 或 A + B ,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。
(2)例如,"","()","(())()" 和 “(()(()))” 都是有效的括号字符串。
(3)如果有效字符串 s 非空,且不存在将其拆分为 s = A + B 的方法,我们称其为原语(primitive),其中 A 和 B 都是非空有效括号字符串。
(4)给出一个非空有效字符串 s,考虑将其进行原语化分解,使得:s = P_1 + P_2 + … + P_k,其中 P_i 是有效括号字符串原语。
(5)对 s 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 s 。
(6)示例如下
输入:s = “(()())(())”
输出:"()()()"
解释:
输入字符串为 “(()())(())”,原语化分解得到 “(()())” + “(())”,
删除每个部分中的最外层括号后得到 “()()” + “()” = “()()()”。
解决思路
- 用cnt记录左右括号的差值,当遇到左括号时,cnt的值加1。当遇到右括号时,cnt的值减1。
- cnt等于0的位置就是最外层括号的位置。当cnt等于0时,去除最外层括号,保留最外层括号内的子串,然后将所有子串拼接成一个字符串,即为答案。
代码
# include <stdio.h>
# include <string>
using namespace std;
class Solution {
public:
string removeOuterParentheses(string s) {
string ret;
int cnt = 0; // 记录左右括号的差值。
int pre = 0; // 记录当前括号序列的起始位置,如(()())的起始位置。
for (int i = 0; i < s.size(); i++) {
if ('(' == s[i]) {
cnt += 1; // 遇到左括号,cnt的值加1
} else {
cnt -= 1; // 遇到右括号,cnt的值减1
}
// 当cnt=0时,去除最外层的括号(即只保留最外层括号内部的元素),通过子串截取实现
if (0 == cnt) {
// 子串的下标从pre + 1开始,长度为i - pre - 1
ret += s.substr(pre + 1, i - pre - 1);
pre = i + 1; // 指向下一个括号序列的起点
}
}
return ret;
}
};
int main() {
Solution *solution = new Solution();
string s = "(()())(())";
printf("%s\n", solution->removeOuterParentheses(s).c_str());
return 0;
}
- Python代码
# -*- coding: utf-8 -*-
class Solution:
def __init__(self):
pass
def removeOuterParentheses(self, s: str) -> str:
ret: str = ''
cnt: int = 0 # 记录左右括号的差值。
pre: int = 0 # 记录当前括号序列的起始位置,如(()())的起始位置。
for i in range(len(s)):
if '(' == s[i]:
cnt += 1 # 遇到左括号,cnt的值加1
else:
cnt -= 1 # 遇到右括号,cnt的值减1
# 当cnt=0时,去除最外层的括号(即只保留最外层括号内部的元素),通过切片取值实现
# 子串的起始下标为pre + 1开始,结束下标为i - 1
if 0 == cnt:
ret += s[pre + 1: i]
pre = i + 1 # 指向下一个括号序列的起点
return ret
def main():
solution = Solution()
s = "(()())(())"
print(solution.removeOuterParentheses(s))
if __name__ == "__main__":
main()
说明
- 对应LeetCode第1021题。
- 链接:https://leetcode-cn.com/problems/remove-outermost-parentheses/