leetcode1190. 反转每对括号间的子串【M】

题目

给出一个字符串 s(仅含有小写英文字母和括号)。

请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。

注意,您的结果中 不应 包含任何括号。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

提示:

0 <= s.length <= 2000
s 中只有小写英文字母和括号
我们确保所有括号都是成对出现的

思路

遇见左括号入栈,遇见右括号出栈存入队列,直到弹出左括号,队列再入栈(改变顺序),直到栈空

答案

class Solution {
public:
    string reverseParentheses(string s) {
        //遇见左括号入栈,遇见右括号出栈存入队列,直到弹出左括号,队列再入栈,直到栈空
        stack<char> re;
        vector<char> out;
        queue<char> temp;
        int len = s.size();
        for (int i=0;i<len;i++){
            //处理括号外的值。
            if(re.empty()&&s[i]!='('){
                out.push_back(s[i]);
            }
            //字母和左括弧入栈
            else{
                if(s[i]!=')') re.push(s[i]);
                if(s[i]==')'){
                    while(re.top()!='('){
                        temp.push(re.top());
                        re.pop();
                    }
                    //弹出最上面的左括弧
                    re.pop();
                    //逆序存入栈
                    if(!re.empty()){
                        while(!temp.empty()){
                            re.push(temp.front());
                            temp.pop();
                        }
                    }else{
                        while(!temp.empty()){
                            out.push_back(temp.front());
                            temp.pop();
                        }
                    }
                }  
            }
        }
        return string(out.begin(),out.end());
    }
};
}

时间复杂度:O(n)
空间复杂度:O(n)

问题与改进

看了下官方题解我对c++还是太不熟了。比我简练多了www。还有一个思路和我一致的,学习下人家的写法:

class Solution {
public:
    string reverseParentheses(string s) {
        if (!s.length()) return "";
        string strStack;
        // 遍历原字符串
        for (int i = 0; i < s.length(); ++i) {
            // 只要不是右括号,就入栈
            if (s[i] != ')') {
                strStack += s[i];
            }
            else {
                string tempStr;
                // 左括号和右括号之间的,就是“当前层”字符串
                while (strStack.back() != '(') {
                    // 使用中间变量存储“当前层”字符串,利用栈的先入后出特性实现反转
                    tempStr += strStack.back();
                    strStack.pop_back();
                }
                strStack.pop_back();  // 去掉左括号
                strStack += tempStr;  // 把反转后的部分重新入栈
            }
        }
        return strStack;
    }
};

作者:bingge
链接:https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/solution/li-yong-zhan-xian-ru-hou-chu-de-te-xing-v5x1s/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

方法一

class Solution {
public:
    string reverseParentheses(string s) {
        stack<string> stk;
        string str;
        for (auto &ch : s) {
            if (ch == '(') {
                stk.push(str);
                str = "";
            } else if (ch == ')') {
            	//竟然可以直接reverse
                reverse(str.begin(), str.end());
                str = stk.top() + str;
                stk.pop();
            } else {
            	//string原来也能push...
                str.push_back(ch);
            }
        }
        return str;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/solution/fan-zhuan-mei-dui-gua-hao-jian-de-zi-chu-gwpv/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本题要求按照从括号内到外的顺序进行处理。

对于括号序列相关的题目,通用的解法是使用递归或栈。本题中我们将使用栈解决。

我们从左到右遍历该字符串,使用字符串str 记录当前层所遍历到的小写英文字母。对于当前遍历的字符:

如果是左括号,将 str 插入到栈中,并将str 置为空,进入下一层;

如果是右括号,则说明遍历完了当前层,需要将str 反转,返回给上一层。具体地,将栈顶字符串弹出,然后将反转后的str 拼接到栈顶字符串末尾,将结果赋值给 str。

如果是小写英文字母,将其加到str 末尾。

注意到我们仅在遇到右括号时才进行字符串处理,这样可以保证我们是按照从括号内到外的顺序处理字符串。

复杂度分析

时间复杂度:O(n2),其中 n 为字符串的长度。栈的最大深度为 O(n),每一层处理的时间复杂度主要为反转的时间复杂度,为O(n),因此总时间复杂度为 O(n2)。

空间复杂度:O(n),其中 n 为字符串的长度。对于任意时刻,字符串中的任意一个字符至多只被栈中的一个位置包含一次。

方法二

我们可以将括号的反转理解为逆序地遍历括号,如下图:

在这里插入图片描述

第一步我们向右移动到左括号,此时我们跳跃到该左括号对应的右括号(进入了更深一层);
第二到第三步我们在括号内部向左移动(完成了更深层的遍历);
第四步我们向左移动到左括号,此时我们跳跃到该左括号对应的右括号(返回到上一层);
第五步我们在括号外向右移动(继续遍历)。
读者们可以自行尝试模拟两层乃至多层括号嵌套的移动方案,规律可以从当前的单层括号中总结出来。

假设我们沿着某个方向移动,此时遇到了括号,那么我们只需要首先跳跃到该括号对应的另一个括号所在处,然后改变我们的移动方向即可。这个方案同时适用于遍历时进入更深一层,以及完成当前层的遍历后返回到上一层的方案。

在实际代码中,我们需要预处理出每一个括号对应的另一个括号所在的位置,这一部分我们可以使用栈解决。当我们预处理完成后,即可在线性时间内完成遍历,遍历的字符串顺序即为反转后的字符串。

class Solution {
public:
    string reverseParentheses(string s) {
        int n = s.length();
        vector<int> pair(n);
        stack<int> stk;
        for (int i = 0; i < n; i++) {
            if (s[i] == '(') {
                stk.push(i);
            } else if (s[i] == ')') {
                int j = stk.top();
                stk.pop();
                pair[i] = j, pair[j] = i;
            }
        }

        string ret;
        int index = 0, step = 1;
        while (index < n) {
            if (s[index] == '(' || s[index] == ')') {
                index = pair[index];
                step = -step;
            } else {
                ret.push_back(s[index]);
            }
            index += step;
        }
        return ret;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/solution/fan-zhuan-mei-dui-gua-hao-jian-de-zi-chu-gwpv/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

复杂度分析

时间复杂度:、O(n),其中 n 为字符串的长度。预处理出括号的对应关系的序列的时间复杂度为 O(n),遍历字符串的时间复杂度同样为 O(n)。

空间复杂度:O(n),其中 n 为字符串的长度。栈的大小不会超过 n,以及我们需要 O(n) 的空间记录括号的对应关系

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第 296 章 使用 Javascript 的 LeetCode 解决方案 var :smiling_face_with_sunglasses: = Easy , :neutral_face: = Medium , :fearful_face: = Hard 1 :neutral_face: 二和 2 :neutral_face: 两个数字相加 3 :neutral_face: 无重复字符的最长 4 :fearful_face: 两个有序数组的中位数 5 :neutral_face: 最长回文 6 :smiling_face_with_sunglasses: 之字形换 7 :smiling_face_with_sunglasses: 整数 8 :smiling_face_with_sunglasses: 字符到整数 (atoi) 9 :smiling_face_with_sunglasses: 回文数 10 :fearful_face: 正则表达式匹配 11 :neutral_face: 盛水最多的容器 12 :neutral_face: 整数罗马 13 :smiling_face_with_sunglasses: 罗马到整数 14 :smiling_face_with_sunglasses: 最长公共前缀 15 :neutral_face: 3总和 16 :neutral_face: 3和最近 17 :neutral_face: 电话号码的字母组合 18 :neutral_face: 4总和 19 :smiling_face_with_sunglasses: 从列表末尾删除第 N 个节点 20 :smiling_face_with_sunglasses: 有效括号 21 :smiling_face_with_sunglasses: 合并两个排序列表 22 :neutral_face: 生成括号 23 :fearful_face: 合并 k 个排序列表 24 :neutral_face: 成对交换节点 25 :fearful_face: k-Group 中的向节点 26 :smiling_face_with_sunglasses: 从排序数组中删除重复项 27 :smiling_face_with_sunglasses: 删除元素 28 :smiling_face_with_sunglasses: 实现 strStr() 29 :neutral_face: 两个整数相除 30 :fearful_face: 连接所有单词的 31 :neutral_face: 下一个排列 32 :fearful_face: 最长有效括号 33 :fearful_face: 在旋排序数组中搜索 34 :neutral_face: 搜

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值