[leetcode] 基本計算器
阿新 • • 發佈:2020-09-12
本文題目:
- 224.基本計算器:加減法,括號,空格。
- 227.基本計算器II:加減乘除,無括號,空格。
- 772.基本計算器III:加減乘除,括號,空格。
題目 772 需要 Plus 會員,可以看這裡的部落格 。
第三題是位元組跳動線上夏令營的原題。
版本 1 :只考慮個位數
實現需求
- 有空格
- 數字只考慮個位數
- 無括號
- 支援四則運算
實現思路
資料結構課上學過的棧演算法,將數字與操作符分離入棧,同時利用一個 map
來記錄操作符的優先順序。只有當前操作符 x
優先順序嚴格大於棧頂操作符優先順序,才能進棧,否則需要先執行棧頂操作符。
程式碼實現
#define isDigital(x) (('0' <= (x)) && ((x) <= '9')) #define isSign(x) (((x) == '+') || ((x) == '-') || ((x) == '*') || ((x) == '/')) class Solution { public: unordered_map<char, int> cmp = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}}; int calculate(string s) { stack<int> numbers; stack<char> signs; for (char x : s) { if (isDigital(x)) numbers.push(x - '0'); else if (isSign(x)) { if (signs.empty() || (cmp[x] > cmp[signs.top()])) signs.push(x); else { while (!signs.empty() && cmp[x] <= cmp[signs.top()]) exec(numbers, signs); signs.push(x); } } } while (!signs.empty()) exec(numbers, signs); assert(numbers.size() == 1); return numbers.top(); } // exec 函式表示對棧頂操作符運算,該函式不會變 void exec(stack<int> &nums, stack<char> &signs) { int a, b, val; char op; op = signs.top(), signs.pop(); b = nums.top(), nums.pop(); a = nums.top(), nums.pop(); switch (op) { case '+': val = a + b; break; case '-': val = a - b; break; case '*': val = a * b; break; case '/': val = a / b; break; default: assert(0); } nums.push(val); } };
版本 2 :考慮任意位數字
實現需求
- 有空格
- 數字任意多位
- 無括號
- 支援四則運算
實現思路
遇見數字,繼續往前掃描,直到遇到非數字,這一整個子串轉換為一個 int
.
程式碼實現
這樣就能通過題目 227 啦~
int calculate(string s) { stack<int> numbers; stack<char> signs; int len = s.length(); for (int i = 0; i < len; i++) { char x = s[i]; if (isDigital(x)) { int j = i; while (isDigital(s[j])) j++; numbers.push(stoi(s.substr(i, j - i))); i = j - 1; } else if (isSign(x)) { if (signs.empty() || (cmp[x] > cmp[signs.top()])) signs.push(x); else { while (!signs.empty() && cmp[x] <= cmp[signs.top()]) exec(numbers, signs); signs.push(x); } } } while (!signs.empty()) exec(numbers, signs); assert(numbers.size() == 1); return numbers.top(); }
版本 3 :考慮括號
實現需求
- 有空格
- 數字任意多位
- 帶括號
- 支援四則運算
這樣就是位元組筆試題目啦。
實現思路
很明顯,對於帶括號的表示式 1+2*(1+2*(3))
,括號中是一個子表示式,同樣要進行求值處理,顯示需要採用遞迴做法。
那麼現在需要解決的就是:當遇到 '('
時,找到該 '('
包圍的子表示式。需要使用括號匹配演算法。
程式碼實現
可以通過 224 ,估計 772 也行(沒會員,窮)。
int calculate(string s) { stack<int> numbers; stack<char> signs; int len = s.length(); for (int i = 0; i < len; i++) { char x = s[i]; if (isDigital(x)) { int j = i; while (isDigital(s[j])) j++; numbers.push(stoi(s.substr(i, j - i))); i = j - 1; } else if (isSign(x)) { if (signs.empty() || (cmp[x] > cmp[signs.top()])) signs.push(x); else { while (!signs.empty() && cmp[x] <= cmp[signs.top()]) exec(numbers, signs); signs.push(x); } } else if (x == '(') { int flag = 0; int j = i; do { if (s[j] == '(') flag++; else if (s[j] == ')') flag--; j++; } while (flag != 0); numbers.push(calculate(s.substr(i + 1, j - 1 - i - 1))); i = j - 1; } } while (!signs.empty()) exec(numbers, signs); assert(numbers.size() == 1); return numbers.top(); }