- 括号的分数
给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:
()
得 1 分。
AB
得 A + B 分,其中 A 和 B 是平衡括号字符串。
(A)
得 2 * A 分,其中 A 是平衡括号字符串。
示例 1:
输入: “()”
输出: 1
示例 2:
输入: “(())”
输出: 2
示例 3:
输入: “()()”
输出: 2
示例 4:
输入: “(()(()))”
输出: 6
提示:
S 是平衡括号字符串,且只含有 ( 和 ) 。
2 <= S.length <= 50
经典题,时间和空间都是O(N)
的,但是官方题解可以做到O(1)
空间
- 我们把原字符串看成是被一个大
()
包裹起来的 - 考虑递归,每次遇到
(
就往下递归,每次遇到)
就跳出函数 - 递归过程可用栈模拟
- 深度为
i
的sum[i]
可以看成是深度为i+1
的乘上2倍,即 2 ∗ ∑ i = 1 k s u m [ i + 1 ] 2*\sum_{i=1}^{k}sum[i+1] 2∗∑i=1ksum[i+1]
class Solution {
public:
//栈模拟递归 时空都是O(N) 非正解,官方题解做到了O(1)空间
int scoreOfParentheses(string S) {
stack<int> lef_idx; //存储左括号的下标
int sum[64] = { 0 }; //sum[i]存储深度为i的括号累加和
int cur_level = 0; //当前深度
for(int i=0; i<S.length(); i++) {
char ch = S[i];
if(ch == '(') { //遇到'('就递归深度+1
lef_idx.push(i); //记得把当前'('的下标入栈
cur_level ++;
} else if(ch == ')') {
if(lef_idx.top()+1 == i) //一对得分为1的"()"的下标距离相差1,则就是为什么要用栈记录'('下标的原因
sum[cur_level] = 1;
//当前深度的值乘2返回给上一层
sum[cur_level-1] += (sum[cur_level] << 1);
sum[cur_level--] = 0; //')'出栈, 清空当前层
}
}
return (sum[cur_level] >> 1); //返回结果是sum[0]/2
/**
2* x
0 1 2 3 4 5 6 7 8 9
( ( ) ( ( ) ) ) 原始字符串
( ( ( ) ( ( ) ) ) ) 我们看成是在原始字符串外面添加了一层括号
1 2 2 2 3 3 2 1
*/
}
};
#ifdef debug
signed main() {
Solution s;
cout << s.scoreOfParentheses("()") << endl;
return 0;
}
#endif