持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
题目
给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:
()得 1 分。AB得A + B分,其中 A 和 B 是平衡括号字符串。(A)得2 * A分,其中 A 是平衡括号字符串。
示例 1:
输入: "()"
输出: 1
示例 2:
输入: "(())"
输出: 2
示例 3:
输入: "()()"
输出: 2
示例 4:
输入: "(()(()))"
输出: 6
提示:
S是平衡括号字符串,且只含有(和)。2 <= S.length <= 50
思考
本题难度中等。
字符串匹配类的问题大多可以用栈的方法解决,比如 921.使括号有效的最少添加、1021.删除最外层的括号以及本题。
首先是理解题意。给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:
()得 1 分。AB得A + B分,其中 A 和 B 是平衡括号字符串。(A)得2 * A分,其中 A 是平衡括号字符串。
字符串只含有'('和')',题目的关键在于理解A、B是什么意思。比如字符串'()()'就是AB型的,得分是'1+1=2'。字符串'(())'是'(A)'型的,得分是2*1=2。字符串'(()())'是'(AB)'型的,得分是'2*(1+1)=4'。
我们可以借助栈的方法来解题。遍历字符串,当当前字符是'('时,存入栈中;当当前字符不是')'时,讨论如下:
- 当上一个字符是'('时,我们往栈中存入数字1。
- 当上一个字符是数字时,根据'(A)'和'(AB)'的规则,我们需要累加所有数字,再乘以2。
最后,遍历栈的所有数字,累加求和并返回结果。
解答
方法一:栈
/**
* @param {string} s
* @return {number}
*/
var scoreOfParentheses2 = function(s) {
const deque = []
for (let i = 0; i < s.length; i++) {
if (s[i] === '(') {
deque.push('(')
} else {
let last = deque.pop()
if (last === '(') {
deque.push(1)
} else { // 数字
let sum = last
while ((last = deque.pop()) !== '(') {
sum += last
}
deque.push(sum << 1) // '(1)' or '(11)' 需要对数字求和再乘以2
}
}
}
// 对deque中的数字求和
let ans = 0
while(deque.length > 0) {
ans += deque.pop()
}
return ans
}
// 执行用时:64 ms, 在所有 JavaScript 提交中击败了37.50%的用户
// 内存消耗:40.8 MB, 在所有 JavaScript 提交中击败了96.25%的用户
// 通过测试用例:86 / 86
复杂度分析:
- 时间复杂度:O(n),其中 n 是字符串 s 的长度。
- 空间复杂度:O(n),栈需要的存储空间为 O(n)。