856. 括号的分数
【计算贡献度】其实可以把每一对括号看作某个深度的叶子结点,我们可以根据他所在的层数计算他对最终答案的贡献度,以( () ()(()) )这个为例子,最外层的 () 包裹了一个 () 和一个 ()(()) 然后再把后面的拆分成 () 和 (()),这样其实就相当于三部分的和了,分别是:(()), (()), ((()))这样就成了计算两个深度为2,一个深度为4的括号的和了。
那么深度如何来计算呢,当遇到 '(' 的时候,我们把深度t + 1,当遇到 ')' 的时候,把深度 t - 1,如果前面一个是 '(' ,那么就把答案加上 1 << t。比如 (( )) 这个,t从0到1再到2然后变为1的时候就可以计算对整个的贡献度了,然后后面再遇到 ')' 只是把深度 - 1,相当于跳出括号,不再去加贡献度了。
class Solution {
// 4:33
// 计算贡献度
public int scoreOfParentheses(String s) {
int t = 0, n = s.length(), ans = 0, b = 1;
for (int i = 0; i < n; i++) {
if (s.charAt(i) == '(') {
t++;
} else {
t--;
if (t == 0) {
ans += b; b = 1;
} else {
b *= 2;
}
}
}
return ans;
}
}
【栈模拟】如果用栈来模拟这个过程的话,需要每次遇到 '(' 的时候在栈顶压入一个0作为辅助。每次遇到 '(' 的时候压入一个0,遇到 ')' 的时候弹出栈顶验证,如果是0,就把1和加到栈顶元素上,如果不是0,就把这个数的2倍加上栈顶元素上。
以( () (()) )为例子:栈初始为0
遇到(,变为0, 0
遇到(,变为0, 0, 0
遇到),弹出栈顶0,变为0,0,然后把1和此时栈顶相加变为0, 1
遇到(,变为0, 1, 0
遇到(,变为0, 1, 0, 0
遇到),弹出栈顶0,变为0, 1, 0,然后把1和栈顶相加变为0, 1, 1
遇到),弹出栈顶1,变为0, 1,然后把1 * 2和栈顶元素相加变为0, 3
遇到),弹出栈顶3,变为0,然后把3 * 2 和栈顶元素相加变为6。得到最终答案。
class Solution {
// 栈
// 9:42
// ( () (()) )
// 6
public int scoreOfParentheses(String s) {
Deque stack = new LinkedList();
stack.push(0);
for (var i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(') stack.push(0);
else {
int top = stack.poll();
if (top == 0) stack.push(stack.pop() + 1);
else stack.push(stack.pop() + top * 2);
}
}
int ans = 0;
while (!stack.isEmpty()) ans += stack.poll();
return ans;
}
}