一、题目
给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:
- () 得 1 分。
- AB 得 A + B 分,其中 A 和 B 是平衡括号字符串。
- (A) 得 2 * A 分,其中 A 是平衡括号字符串。
也就是说:
- ( ) = 1
- ( ) ( ) = 1 + 1 = 2
- ( ( ) ) = 1 * 2 = 2
二、思路
1. 递归分治
使用分治思想,通过递归函数实现将整个算式分解并逐步计算,最后得出结果。
递归首先写最小问题的答案,即:当输入的参数为 ' ( ) ' 时,函数要给出结果1。
然后,在遍历了n个字符,并且头部和尾部是一对对应的括号时,有两种可能:
1. 整个算式遍历完毕,则需要剥开最外层括号,将里层的算数值x2。
2. 整个算式未遍历完,说明算式是两个相加的值组成, 则根据当前遍历的数量n,将原参数s进行分割,并将左右两个算式的值相加。
通过上述的递归处理(剥除和切割),最后函数的参数会变为最小问题,即 ' ( ) ' 的值。
2. 栈
使用栈的思想,在遍历算式时计算当前层次中的值。栈顶元素代表最后的括号中包含的值。当遍历得到 ' ) ' 时,如果栈顶元素为0,说明最后的括号为空括号 ' ( ) ' ,值为1,本层括号计算结束,将栈顶元素出栈,将新的栈顶元素的值加上1,表示最后的括号中目前的值加1。由于加法情况永远可以被分解成两个值进行增加,所以只需要一直进行计算就可以得到本层括号的总值。那么,如果栈顶元素不为0,说明是' ( ( ) ) '的情况,值为栈顶元素的2倍,将栈顶元素出栈x2后,加到新的栈顶元素上。
也就是说,例如 ' ( ( ) ( ( ) ) ) ',每个左括号都保存着括号中对应的值,一旦一个括号全部计算完,那么就将其出栈,并把值存放到上层左括号中,也就是栈顶元素。在例子中,栈顶元素首先是0,对应第一个左括号,然后再入栈一个0,第三次时遇到右括号,将该括号出栈后加到外层括号的值上,也就是出栈0,通过计算得到1加到新的栈顶元素上。然后入栈0,入栈0,出栈0,计算得到1,加到新的栈顶元素上,出栈1,计算得到2,加到新的栈顶元素上,出栈3,计算得到6,加到新的栈顶元素上(也就是最终答案)。
因此,首先在栈中要保存一个0,这样在计算完整个算式后,将算式的值和0相加,顺利输出最终的结果。
三、代码
1. 分治
class Solution:
def scoreOfParentheses(self, s: str) -> int:
n = len(s)
if n == 2:
return 1
sum = 0
for i,e in enumerate(s):
sum += 1 if e =='(' else -1
if sum == 0:
if i == n - 1:
return self.scoreOfParentheses(s[1:-1]) * 2
else:
return self.scoreOfParentheses(s[:i+1]) + self.scoreOfParentheses(s[i+1:])
2. 栈
class Solution:
def scoreOfParentheses(self, s: str) -> int:
lib = [0]
for i, e in enumerate(s):
if e == '(':
lib.append(0)
else:
v = lib.pop()
lib[-1] += max(1, 2*v)
return lib[-1]