已通过的题目
题目都一样,稍微改一下输入。代码通过了以下 3 题的测试数据。其中,LeetCode的两题的测试数据不够复杂(下面说明)。代码的正确性,还需要更多的测试数据来测。
LeetCode 227 题的测试数据,没有包含以下两种情况:
1、负数开头。类似:-2+...
2、左括号后的第一个数是负数。类似:2*(-3+4)...
另外,如果有LeetCode会员,可以再提交一下这题:772. 基本计算器 III
代码
#include<iostream>
#include<cstdio>
#include<stack>
#include<map>
using namespace std;
// 装数字的栈
stack<int> num;
// 装符号的栈。从栈底到栈顶方向,符号运算优先级越高
// 优先级越高,越要优先计算
// ) < +、- < *、/ < (
stack<char> opr;
// 存储符号优先级
map<char, int> prio;
void initPriority() {
prio[')'] = 1;
prio['+'] = 2;
prio['-'] = 2;
prio['*'] = 3;
prio['/'] = 3;
prio['('] = 4;
}
// 双目运算符的计算。c:中间的符号;a:左边的数;b:右边的数
int cal(int a, int b, char c) {
if (c=='+') {
return a+b;
}
if (c=='-') {
return a-b;
}
if (c=='*') {
return a*b;
}
if (c=='/') {
return a/b;
}
return 0;
}
void doCal() {
char c = opr.top(); opr.pop();
int b = num.top(); num.pop();
int a = num.top(); num.pop();
int res = cal(a, b, c);
num.push(res);
}
// 特殊情况:-1+...
// (-2+3-...)
// 2+(3-2+1)
// 2+(-2+1)*2/2 2+(2-1)*2
// 1+2*3/2
int calculate(string s) {
initPriority();
// 防止开头是负数的情况
if (s[0]=='-') {
num.push(0);
}
int t=0; // 用于字符串转int值
for(int i=0; i<s.length(); i++) {
if(s[i] == ' ') {
continue;
}
if (isdigit(s[i])) { // 数字
t = 10*t + (s[i]-'0');
if (!isdigit(s[i+1])) {
num.push(t);
t=0;
}
}
else { // 符号
while(!opr.empty() && opr.top()!='(' && prio[ s[i] ] <= prio[ opr.top() ]) {
doCal();
}
if (!opr.empty() && opr.top() == '(' && s[i]==')') {
opr.pop();
} else {
opr.push(s[i]);
// 防止 (-2...的情况
if(s[i]=='(' && s[i+1]=='-') {
num.push(0);
}
}
}
}
while(!opr.empty()) {
doCal();
}
return num.top();
}
int main() {
string s;
while(getline(cin, s)) {
printf("%d\n", calculate(s));
}
return 0;
}