1190. 反转每对括号间的子串

题目

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

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

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

示例 1:

输入:s = “(abcd)”
输出:“dcba”

示例 2:

输入:s = “(u(love)i)”
输出:“iloveu”

示例 3:

输入:s = “(ed(et(oc))el)”
输出:“leetcode”

示例 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

方法一:栈

步骤:

  • 创建一个放字符串的栈, 以及一个保存当前字符的变量
  • 遇到 ( 就将当前的字符串推入栈, 并将当前字符串其设置为空
  • 遇到 ) 就将当前的字符串反转, 然后与栈的顶部元素合并, 将栈的顶部元素弹出
  • 遇到普通的字符就将其添加到当前字符串的尾部
  • 遍历结束返回字符串
class Solution {
    public String reverseParentheses(String s) {
        Deque<String> stack=new LinkedList<String>();
        StringBuffer sb=new StringBuffer();
        int n=s.length();
        for(int i=0;i<n;i++){
            char ch=s.charAt(i);
            if(ch=='('){
                stack.push(sb.toString());
                sb.setLength(0);
            }else if(ch==')'){
                sb.reverse();
                sb.insert(0,stack.pop());
            }else{
                sb.append(ch);
            }
        }
        return sb.toString();
    }
}

复杂度分析

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

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

方法二:预处理括号
在法一的方法中不足之处在于使用reverse()函数的时间消耗非常巨大, 对于每一对符号我们都要反转其括号内的字符使得时间复杂度提升到O(n2). 我们发现其实我们并不需要真的取反转字符,只需要得到一个顺序正确的字符串返回即可,因此我们可以对括号进行预处理,交换其左右括号的坐标。因此我们在向右遍历到左括号时实则跳到了右括号向左遍历。

将括号的反转理解为逆序地遍历括号
在这里插入图片描述

  • 向右移动到左括号,此时我们跳跃到该左括号对应的右括号(进入了更深一层);
  • 第二到第三步我们在括号内部向左移动(完成了更深层的遍历);
  • 第四步我们向左移动到左括号,此时我们跳跃到该左括号对应的右括号(返回到上一层);
  • 第五步我们在括号外向右移动(继续遍历)。
class Solution {
    public String reverseParentheses(String s) {
        int n=s.length();
        int[] pair=new int[n];
        Deque<Integer> stack=new LinkedList<Integer>();
        
        //先去找匹配的括号,i 会跳到其 pair[i]的位置
        for(int i=0;i<n;i++){
            char ch=s.charAt(i);
            if(ch=='('){
                stack.push(i);
            }else if(ch==')'){
                int j=stack.pop();
                pair[i]=j;
                pair[j]=i;
            }
        } 
        StringBuffer sb=new StringBuffer();
        int index=0,step=1;
        // index是当前位置 |step是方向,+就是向右穿
        while(index<n){
            if(s.charAt(index)=='('||s.charAt(index)==')'){      
                // 如果碰到括号,那么去他对应的括号,并且将方向置反
                index=pair[index];
                //变换遍历方向
                step=-step;
            }else{
                sb.append(s.charAt(index));
            }
            index+=step;
        }
        return sb.toString();
    }
}

复杂度分析

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

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

链接:https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/solution/zhan-dong-tu-yan-shi-by-xiaohu9527-hua8/
链接:https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses/solution/chong-dong-fa-yi-ge-zhi-zhen-de-qi-huan-piao-liu-b/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值