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 <= 2000s中只有小写英文字母和括号- 题目测试用例确保所有括号都是成对出现的
二、题解:
方法一 出入栈
- 原理。主要是通过出入栈法及reverse()方法调换原字符串。
- 思路。
- 创建一个放字符串的栈, 以及一个保存当前字符的变量
- 遇到 ( 就将当前的字符串推入栈, 并将当前字符串其设置为空
- 遇到 ) 就将当前的字符串反转, 然后与栈的顶部元素合并, 将栈的顶部元素弹出
- 遇到普通的字符就将其添加到当前字符串的尾部
- 遍历结束返回字符串
代码:
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
};
方法二 遍历排序法
- 原理。记录每一次括号的位置,根据括号位置信息进行正序或逆序排序进行遍历输出。
- 思路。
- 第一步我们向右移动到左括号,此时我们跳跃到该左括号对应的右括号(进入了更深一层);
- 第二到第三步我们在括号内部向左移动(完成了更深层的遍历);
- 第四步我们向左移动到左括号,此时我们跳跃到该左括号对应的右括号(返回到上一层);
- 第五步我们在括号外向右移动(继续遍历)。
代码:
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
};
方案比较
- 方案一使用的是出入栈法,但是由于有reverse操作,时间复杂度是O(n2)
- 方案二使用的是遍历排序法,记录每一次括号的位置,根据括号位置信息进行正序或逆序排序进行遍历输出,都是一次循环,所以时间复杂度是O(n)。
三、总结
- 此题可以出入栈法和遍历排序法两种方案
- 出入栈法主要是通过出入栈法及reverse()方法调换原字符串。
- 遍历排序法记录每一次括号的位置,根据括号位置信息进行正序或逆序排序进行遍历输出。
文中如有错误,欢迎在评论区指正