给出一个字符串 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"
题解 :
/**
* @param {string} s
* @return {string}
*/
// 方法一:栈 O(n2)
var reverseParentheses = function (s) {
let stack = [];
let str = ''
for (let v of s) {
// 遇到左括号入栈 初始化str
if (v == '(') {
stack.push(str)
str = ''
// 遇到有括号 先把str翻转 然后把栈顶元素加上当前str后 栈顶出栈
} else if (v == ')') {
str = str.split('').reverse().join('')
str = stack[stack.length - 1] + str
stack.pop()
// 如果遇到非左括号和右括号时 str累计加
} else {
str += v
}
}
return str
}
我们可以将括号的反转理解为逆序地遍历括号,如下图:
-
第一步我们向右移动到左括号,此时我们跳跃到该左括号对应的右括号(进入了更深一层)
-
第二到第三步我们在括号内部向左移动(完成了更深层的遍历)
-
第四步我们向左移动到左括号,此时我们跳跃到该左括号对应的右括号(返回到上一层)
-
第五步我们在括号外向右移动(继续遍历)
// 方法二:预处理括号 O(n)
var reverseParentheses = function (s) {
let n = s.length;
const stack = [];
// 根据字符转长度 创建对应数组 并且每位填充 0
// 负责记录翻转括号下标值
const pair = new Array(n).fill(0)
// 对字符串的左右括号进行翻转记录
// 字符串内每个左括号对应的有括号下标位置
// 例子:
// s = "(u(love)i)"
// pair = [9, 0, 7, 0, 0, 0, 0, 2, 0, 0]
for (let i = 0; i < n; i++) {
// 当遇到左括号时 当前下标入栈
if (s[i] == '(') {
stack.push(i)
}
// 左右括号下标翻转
// 当遇到右括号时 pair内当前位置 等于左括号位置下标
// pair内左括号位置等于 当前位置下标
if (s[i] == ')') {
let j = stack.pop()
pair[i] = j
pair[j] = i
}
}
let index = 0;
let step = 1;
const sb = []
while (index < n) {
// 当遇到s字符串的左括号时 index位置跳转至对应的右位置
// step 为负数 向左遍历
// 当遇到s字符串的右括号时 index位置跳转至对应的左位置
// step 为正数 向右遍历
if (s[index] == '(' || s[index] == ')') {
index = pair[index]
step = -step
} else {
sb.push(s[index])
}
index += step
}
return sb.join('')
}
来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。