题目来源
题目描述
class Solution {
public:
int scoreOfParentheses(string s) {
}
};
题目解析
栈
思路
class Solution {
public:
int scoreOfParentheses(string pstr) {
std::stack<int> stk;
for (int i = 0; i < pstr.size(); ++i) {
if(pstr[i] == '('){
stk.push(0); //遇到左括号入栈,用0模拟
}else{
auto top = stk.top(); //栈顶为0即栈顶为左括号,此时为()的情况,得1分
if(stk.top() == 0){
stk.pop();
stk.push(1);
}else{ //栈顶不为左括号即为(ABC)的情况,得分为(A+B+C)*2
int score = 0;
while (stk.top() != 0){
score += stk.top();
stk.pop();
}
stk.pop();
stk.push(score * 2);
}
}
}
int score = 0;
while (!stk.empty() ){
score += stk.top();
stk.pop();
}
return score;
}
};
思路
-
首先要明确一个重点:这里边真正有作用的就是"()“这对括号,所有的值的来源都是由”()"经过了加和或者相乘得来的
-
不妨直接做一个替换:既然"()“的值为1,我们就直接利用replace函数把”()“替换成"1”,那我们就得到了 “(())“变为”(1)”; “()()“变为"11”;”(()(()))“变为”(1(1))"
-
分析一下替换后的内容,“(1(1))” 直观上是(1+1×2)×2=1×2+1×2×2 (加法分配律) 如此一来,直接看当前位置的1的前面有多少个"(“就可以知道×几个2了,如第一个"1"前有一个,第二个"1"前有两个。同理呢,遇见”)“我们就要除以2了:(1)(1)=1×2+1×2 第二个"1"前有两个”(“和一个”)“,会抵消一个,就剩一个”(",所以×2。
综上,我们遇见"(“就直接*2好了,遇见”("就直接/2,遇见"1"就赶紧加上去。
class Solution:
def scoreOfParentheses(self, s: str) -> int:
s=s.replace('()','1')
nums=1
res=0
for i in s:
if i == "(":
nums*=2
if i == ")":
nums/=2
if i == "1":
res+=nums
return int(res)
递归
思路
- 先找出每一个最外层的括号,再对其中间的整体部分调用递归
实现
class Solution {
public:
int scoreOfParentheses(string pstr) {
int res = 0, n = pstr.size();
for (int i = 0; i < n; ++i) {
if(pstr[i] == ')'){
continue;
}
//找部分合法的括号字符串: 使用一个计数器,遇到左括号,计数器自增1,反之右括号计数器自减1,那么当计数器为0的时候,就是一个合法的字符串了
int pos = i + 1, cnt = 1;
while (cnt != 0){ // (
(pstr[pos++] == '(') ? ++cnt : --cnt;
}
// (((())))(
// i p
// 对除去最外层的括号的中间内容调用递归 ((()))
int cur = scoreOfParentheses(pstr.substr(i + 1, pos - i - 2));
res += max(2 * cur, 1);
i = pos - 1;
}
return res;
}
};