1190. Reverse Substrings Between Each Pair of Parentheses

You are given a string s that consists of lower case English letters and brackets.

Reverse the strings in each pair of matching parentheses, starting from the innermost one.

Your result should not contain any brackets.

Example 1:

Input: s = "(abcd)"
Output: "dcba"

Example 2:

Input: s = "(u(love)i)"
Output: "iloveu"
Explanation: The substring "love" is reversed first, then the whole string is reversed.

Example 3:

Input: s = "(ed(et(oc))el)"
Output: "leetcode"
Explanation: First, we reverse the substring "oc", then "etco", and finally, the whole string.

Example 4:

Input: s = "a(bcdefghijkl(mno)p)q"
Output: "apmnolkjihgfedcbq"

Constraints:

  • 0 <= s.length <= 2000
  • s only contains lower case English characters and parentheses.
  • It’s guaranteed that all parentheses are balanced.

这道题给了一个只含有小写字母和括号的字符串s,现在让从最内层括号开始,每次都反转括号内的所有字符,然后可以去掉该内层括号,依次向外层类推,直到去掉所有的括号为止。可能有的童鞋拿到题后第一反应可能是递归到最内层,翻转,然后再一层一层的出来。这样的做的话就有点麻烦了,而且保不齐还有可能超时。比较好的做法就是直接遍历这个字符串,当遇到字母时,将其加入结果 res,当遇到左括号时,将当前 res 的长度加入一个数组 pos,当遇到右括号时,取出 pos 数组中的最后一个数字,并翻转 res 中该位置到结尾的所有字母,因为这个区间刚好就是当前最内层的字母,这样就能按顺序依次翻转所有括号中的内容,最终返回结果 res 即可,参见代码如下:

解法一:

class Solution {
public:
    string reverseParentheses(string s) {
        string res;
        vector<int> pos;
        for (char c : s) {
            if (c == '(') {
                pos.push_back(res.size());
            } else if (c == ')') {
                int idx = pos.back();
                pos.pop_back();
                reverse(res.begin() + idx, res.end());
            } else {
                res.push_back(c);
            }
        }
        return res;
    }
};

这道题居然还有 O(n) 的解法,由 lee215 大神提出的一种类似虫洞的解法,惊为天人,评论区有人调侃到 LeetCode 应该改名为 Lee’sCode,哈哈,确实很形象。这种解法首先要建立每一对括号位置之间的映射,而且是双向映射,即左括号位置映射到右括号位置,同时右括号位置也要映射到左括号位置,这样在第一次遇到左括号时,就可以直接跳到对应的右括号,然后往前遍历,当下次遇到右括号时,就直接跳到其对应的左括号,然后往后遍历,这样实际相当于在嵌套了两层的括号中,是不用翻转的,因为只有奇数嵌套才需要翻转,用这种逻辑遍历,就可以串出最终正确的结果,由于遍历顺序不停在改变,所以用一个变量d来控制方向,初始化为1,当需要变换了就取相反数即可,参见代码如下:

解法二:

class Solution {
public:
    string reverseParentheses(string s) {
        string res;
        int n = s.size();
        vector<int> pos, pair(n);
        for (int i = 0; i < n; ++i) {
            if (s[i] == '(') {
                pos.push_back(i);
            } else if (s[i] == ')') {
                int idx = pos.back();
                pos.pop_back();
                pair[i] = idx;
                pair[idx] = i;
            }
        }
        for (int i = 0, d = 1; i < n; i += d) {
            if (s[i] == '(' || s[i] == ')') {
                i = pair[i];
                d = -d;
            } else {
                res += s[i];
            }
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1190

参考资料:

https://leetcode.com/problems/reverse-substrings-between-each-pair-of-parentheses/

https://leetcode.com/problems/reverse-substrings-between-each-pair-of-parentheses/discuss/382367/Simple-Stack-and-Queue-Solution

https://leetcode.com/problems/reverse-substrings-between-each-pair-of-parentheses/discuss/383670/JavaC%2B%2BPython-Tenet-O(N)-Solution

LeetCode All in One 题目讲解汇总(持续更新中…)


转载请注明来源于 Grandyang 的博客 (grandyang.com),欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 grandyang@qq.com

💰


微信打赏


Venmo 打赏

(欢迎加入博主的知识星球,博主将及时答疑解惑,并分享刷题经验与总结,试运营期间前五十位可享受半价优惠~)

×

Help us with donation