解法一、遞迴
🔹 大式子拆成小式子
依照 優先度由低而高、由後往前 的順序處理
+, - → *, /, % → (, )
當一個式子沒有任何運算符號 (代表他只剩數字),返回數值
當一個式子運算完成,返回數值
由於括號優先度高 (遞迴中要最後處理)
因此需要一個變數 layer 紀錄當前位置括號的層數
層數 = 0 時,才能處理 +, -, *, /, %
當最左最右都是刮號才去括號
遞迴代碼
(begin1 ~ end1 為前半式子,begin2 ~ end2 為後半式子)
int calculate(int begin, int end){
// find + -
return calculate(begin1, end1) [op] calculate(begin2, end2);
// find * / %
return calculate(begin1, end1) [op] calculate(begin2, end2);
// find ( )
return calculate(begin1, end2);
// only find number
return num;
}
12 * 34 * 56 + 78
+ 明顯需要最後處理
於是由後往前找到 + 後
將問題拆成 [12 * 34 * 56] + [78] 兩個式子遞迴
遞迴會先處理完這兩個式子,再處理加法
以下是完整的步驟 (中括號代表式子的拆法)
- 拆
+號:[12 * 34 * 56] + [78] - 拆
*號:[[12 * 34] * 56] + [78] - 拆
*號:[[[12] * [34]] * 56] + [78] - 返回結果:
22926
✅ 完整代碼
評分結果(參考) : AC (2ms, 332KB)
#include <bits/stdc++.h>
using namespace std;
#define int long long
string s;
int s2i(int begin_, int end_){
int num = 0;
for (int i=begin_; i<end_; i++) {
num = num*10 + (s[i]-'0');
}
return num;
}
int calculate(int begin_, int end_) {
if (begin_ >= end_) return 0;
// handle + -
int layer = 0;
for(int i=end_-1; i>=begin_; i--) {
if(s[i] == ')') layer++;
else if(s[i] == '(') layer--;
else if((s[i] == '+' || s[i] == '-') && layer == 0) {
if(s[i] == '+') return calculate(begin_, i-1) + calculate(i+2, end_);
else return calculate(begin_, i-1) - calculate(i+2, end_);
}
}
// handle * / %
layer = 0;
for(int i = end_-1; i>=begin_; i--) {
if(s[i] == ')') layer++;
else if(s[i] == '(') layer--;
else if(layer == 0) {
if(s[i] == '*') return calculate(begin_, i-1) * calculate(i+2, end_);
if(s[i] == '/') return calculate(begin_, i-1) / calculate(i+2, end_);
if(s[i] == '%') return calculate(begin_, i-1) % calculate(i+2, end_);
}
}
// handle ( )
if(s[begin_] == '(' && s[end_-1] == ')') {
return calculate(begin_+2, end_-2);
}
return s2i(begin_, end_);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
while(getline(cin, s)) {
cout << calculate(0, s.size()) << endl;
}
}