题目
给出一个字符串 s(仅含有小写英文字母和括号)。
请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。
注意,您的结果中 不应 包含任何括号。
示例 1:
输入:s = "(abcd)"
输出:"dcba"
示例 2:
输入:s = "(u(love)i)"
输出:"iloveu"
解释:先反转子字符串 "love" ,然后反转整个字符串。
示例 3:
输入:s = "(ed(et(oc))el)"
输出:"leetcode"
解释:先反转子字符串 "oc" ,接着反转 "etco" ,然后反转整个字符串。
示例 4:
输入:s = "a(bcdefghijkl(mno)p)q"
输出:"apmnolkjihgfedcbq"
提示:
0 <= s.length <= 2000
s 中只有小写英文字母和括号
题目测试用例确保所有括号都是成对出现的
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
思路是官方题解的方法二(预处理括号),我感觉这个方法非常像传送门,简单说一下传送方法:从字符串开头开始遍历,如果遇到普通字符,则写入答案中,如果遇到的是括号,那么一定存在一个对应的括号,如果是 (
就传到其对应的 )
,如果是 )
就传到其对应的 (
,然后改变遍历的方向。
以 s = "(ed(et(oc))el)"
为例,一开始方向向右,先遇到的是下标 0 的 (
,那就被传送到字符串末端的 )
,并且方向改为向左,然后是两个正常字符 l
e
,写入答案中;再遇到一个 )
,传送到下标为 3 的 (
,并且方向改为向右,然后是两个正常字符 e
t
,以此类推,最后可以得到完整的答案 leetcode
,并且下标会指向 s 的尾后位置越界,从而结束循环。
这个方法的本质就是用遍历方向的变化来描述逆序,额外需要做的事情是我们需要提前遍历一遍字符串得到每一个括号所对应的括号在什么位置,这个使用栈就可以很好地得到。
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
C++ 代码
class Solution {
public:
string reverseParentheses(string s) {
if (s.empty())
return string();
string ans;
vector<int> portal(s.size());
vector<int> stack;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '(')
stack.push_back(i);
else if (s[i] == ')') {
portal[i] = stack.back();
portal[stack.back()] = i;
stack.pop_back();
}
}
int index = 0;
bool headingRight = true;
while (index < s.size()) {
if (s[index] != '(' && s[index] != ')') {
ans.push_back(s[index]);
} else {
index = portal[index];
headingRight = !headingRight;
}
index += headingRight ? 1 : -1;
}
return ans;
}
};