题目来源
题目描述
给定一个字符串str,str表示一个公式,公式里可能有整数、加减乘除符号和左右 括号,返回公式的计算结果。
【举例】
str="48*((70-65)-43)+8*1",返回-1816。
str="3+1*4",返回7。
str="3+(1*4)",返回7。
【说明】
-
可以认为给定的字符串一定是正确的公式,即不需要对str做公式有效性检查。
-
如果是负数,就需要用括号括起来,比如"4* (-3)“。但如果负数作为公式的开头 或括号部分的开头,则可以没有括号,比如”-3* 4"和"(-3* 4)"都是合法的。
-
不用考虑计算过程中会发生溢出的情况。
class Solution {
public:
/**
* @param s: the expression string
* @return: the answer
*/
int calculate(string &s) {
// Write your code here
}
};
题目解析
思路
怎么思考:
(1)先只考虑没有括号,而且只有正数相加减的情况
(2)然后考虑有括号
(3)最后思考:开头的负数的情况
最简单的情况:当没有
()
时
图示待更新(应该准备一个队列,因为最终结算答案的时候需要从最底下出栈)
定义递归函数 i n t f ( i n t i ) int f(int i) intf(inti)。表示:
- 从 i i i位置出发,遇到
)
或者整个字符串终止位置时停止,返回两个值
- ans
- f函数算到哪个位置了
遇到(
就交给递归去搞
开头为负怎么计算
“0”、“-”压栈
注意特别处理最后一个数字
实现
class Solution {
void pushDeque(std::deque<std::string> &queue, int num){
if(!queue.empty()){
int curr = 0;
std::string top = queue.back(); queue.pop_back();
if(top == "+" || top == "-"){
queue.push_back(top);
}else{
curr = atoi(queue.back().c_str()); queue.pop_back();
num = top == "*" ? curr * num : curr / num;
}
}
queue.push_back(std::to_string(num));
}
int calNum(std::deque<std::string> &queue){
int res = 0, num = 0;
bool add = true;
std::string curr;
while (!queue.empty()){
curr = queue.front(); queue.pop_front();
if(curr == "+"){
add = true;
}else if(curr == "-"){
add = false;
}else{
num = atoi(curr.c_str());
res += add ? num : (-num);
}
}
return res;
}
// 请从str[i...]往下算,遇到字符串终止位置或者右括号,就停止
// 返回两个值,长度为2的数组
// 0) 负责的这一段的结果是多少
// 1) 负责的这一段计算到了哪个位置
std::vector<int> f(std::string str, int i){
std::deque<std::string> queue;
int curr = 0;
// 从i出发,开始遍历
while (i < str.size() && str[i] != ')'){
if(str[i] >= '0' && str[i] <= '9'){
curr = curr * 10 + str[i++] - '0';
}else if(str[i] != '('){ // 遇到的是运算符号
pushDeque(queue, curr);
// std::string symbol(1, str[i++]);
queue.emplace_back(1, str[i++]);
curr = 0;
}else{// 遇到左括号了
auto result = f(str, i + 1);
curr = result[0];
i = result[1] + 1;
}
}
pushDeque(queue, curr);
return {calNum(queue), i};
}
public:
/**
* @param s: the expression string
* @return: the answer
*/
int calculate(string &s) {
return f(s, 0)[0];
}
};