思路
一开始直接拿 栈算了, 但是发生了段错误, 原来是可能有多余的括号, QAQ , 有点狗血 , 说实话, 我感觉这个题有点故意恶心人了 , 就是只能用递归写
先看看用栈写的代码, 这个套的yxc的模板写的:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int inf = INT_MAX;
typedef pair<int, int> pii;
typedef priority_queue<int, vector<int>, greater<int>> small_heap;
// #define int long long
stack<int> num;
stack<char> op;
int qmi(int m, int k)
{
int res = 1, t = m;
while (k)
{
if (k & 1)
res = res * t;
t = t * t;
k >>= 1;
}
return res;
}
void eval()
{
auto b = num.top();
num.pop();
auto a = num.top();
num.pop();
auto c = op.top();
op.pop();
int x;
if (c == '+')
x = a + b;
else if (c == '-')
x = a - b;
else if (c == '*')
x = a * b;
else if (c == '/')
x = a / b;
else if (c == '^')
x = qmi(a, b);
num.push(x);
}
unordered_map<char, int> pr{
{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'^', 3}};
int32_t main()
{
string str;
cin >> str;
for (int i = 0; i < str.size(); i++)
{
auto c = str[i];
if (isdigit(c))
{
int x = 0, j = i;
while (j < str.size() && isdigit(str[j]))
x = x * 10 + str[j++] - '0';
i = j - 1;
num.push(x);
}
else if (c == '(')
op.push(c);
else if (c == ')')
{
while (op.top() != '(')
eval();
op.pop();
}
else
{
while (op.size() && op.top() != '(' && pr[op.top()] >= pr[c])
eval();
op.push(c);
}
}
while (op.size())
eval();
cout << num.top() << endl;
return 0;
}
很明显 , 这个代码只适合 合法的表达式计算 , 遇到 ((3 + 4 )
这种, 就会段错误
然后是用分治的方法解决, 看看雨巨的代码:
#include<bits/stdc++.h>
using namespace std;
string n;
int number(int left, int right){
//返回字符串n中[left,right]段的数字
int ans = 0;
for(int i = left; i <= right; i++)
ans = ans * 10 + n[i] - '0';
return ans;
}
int cale(int l, int r){
int cnt = 0, add = 0, mul = 0, power = 0;
for(int i = l; i <= r; i++){
if(n[i] == '(')
cnt++;
else if(n[i] == ')')
cnt--;
else if(!cnt){ //记录括号外的最后一个符号位置,优先级不同的分开记录
switch(n[i]){
case '+':
case '-':
add = i;
case '*':
case '/':
mul = i;
case '^':
power = i;
}
}
}
if(cnt > 0 && n[l] == '(')//去掉多余的括号
return cale(l + 1, r);
else if(cnt < 0 && n[r] == ')')
return cale(l, r - 1);
else if(!cnt && !add && !mul && !power){
//剩下的式子包在括号里或者只剩下数字,则获取这个数字
if(n[l] == '(' && n[r] == ')')
return cale(l + 1, r - 1);
return number(l, r);
}
if(add)
if(n[add] == '+')
return cale(l, add-1) + cale(add+1, r);
else
return cale(l, add-1) - cale(add+1, r);
if(mul)
if(n[mul] == '*')
return cale(l, mul-1) * cale(mul+1, r);
else
return cale(l, mul-1) / cale(mul+1, r);
if(power)
return pow(cale(l, power-1), cale(power+1, r));
return -1;
}
int main(){
cin>>n;
cout<<cale(0,n.length()-1)<<endl;
return 0;
}
这种没考虑第一个是负数的情况, 比如说-1 * 8 ,但是实在写恶心了这道题, 下一道了先