【前端也得会算法】- 1190. 反转每对括号间的子串 [ 中等 ]

171 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

给出一个字符串 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 中只有小写英文字母和括号
  • 题目测试用例确保所有括号都是成对出现的

二、题解:

方法一 出入栈

  • 原理。主要是通过出入栈法及reverse()方法调换原字符串。
  • 思路。
    • 创建一个放字符串的栈, 以及一个保存当前字符的变量
    • 遇到 ( 就将当前的字符串推入栈, 并将当前字符串其设置为空
    • 遇到 ) 就将当前的字符串反转, 然后与栈的顶部元素合并, 将栈的顶部元素弹出
    • 遇到普通的字符就将其添加到当前字符串的尾部
    • 遍历结束返回字符串

test.gif

代码:

var reverseParentheses = function(s) {
    let str=''
    let _tempArr = []
    for(let i =0;i<s.length;i++){
        let char = s[i]
        if(char=='('){
            _tempArr.push(str)
            str=""
        }else if(char==')'){
            str = str.split("").reverse().join("")
            str = _tempArr[_tempArr.length-1] + str
            _tempArr.pop()
        }else{
            str+=char
        }
    }
    return str
};

image.png

方法二 遍历排序法

  • 原理。记录每一次括号的位置,根据括号位置信息进行正序或逆序排序进行遍历输出。
  • 思路。
    • 第一步我们向右移动到左括号,此时我们跳跃到该左括号对应的右括号(进入了更深一层);
    • 第二到第三步我们在括号内部向左移动(完成了更深层的遍历);
    • 第四步我们向左移动到左括号,此时我们跳跃到该左括号对应的右括号(返回到上一层);
    • 第五步我们在括号外向右移动(继续遍历)。

代码:

var reverseParentheses = function(s) {
    let len = s.length
    let arr = new Array(len).fill(0)
    const recordOrder = () => {
        let tempNum = []
        for(let i=0;i<len;i++){
            if(s[i]=='('){
                tempNum.push(i)
            } else if(s[i]==')') {
                const j = tempNum.pop();
                ([arr[i], arr[j]] = [j, i])
            } 
        }
    }
    recordOrder()
    
    let index = 0, step = 1
    let result = ''
    while(index<len){
        if(s[index] === '(' || s[index] === ')'){
            index = arr[index]
            step = - step
        } else {
            result+=s[index]
        }
        index += step;
    }
    return result
};

image.png

方案比较

  • 方案一使用的是出入栈法,但是由于有reverse操作,时间复杂度是O(n2)
  • 方案二使用的是遍历排序法,记录每一次括号的位置,根据括号位置信息进行正序或逆序排序进行遍历输出,都是一次循环,所以时间复杂度是O(n)。

三、总结

  • 此题可以出入栈法遍历排序法两种方案
  • 出入栈法主要是通过出入栈法及reverse()方法调换原字符串。
  • 遍历排序法记录每一次括号的位置,根据括号位置信息进行正序或逆序排序进行遍历输出。

文中如有错误,欢迎在评论区指正