LeetCode探索(145):856-括号的分数

90 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

题目

给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:

  • () 得 1 分。
  • ABA + B 分,其中 A 和 B 是平衡括号字符串。
  • (A)2 * A 分,其中 A 是平衡括号字符串。

示例 1:

输入: "()"
输出: 1

示例 2:

输入: "(())"
输出: 2

示例 3:

输入: "()()"
输出: 2

示例 4:

输入: "(()(()))"
输出: 6

提示:

  1. S 是平衡括号字符串,且只含有 ()
  2. 2 <= S.length <= 50

思考

本题难度中等。

字符串匹配类的问题大多可以用的方法解决,比如 921.使括号有效的最少添加、1021.删除最外层的括号以及本题。

首先是理解题意。给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:

  • () 得 1 分。
  • ABA + 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)。

参考