题目

image.png

思路

  • 本质就是模拟四则运算
  • 需要维护两个栈,op放操作符,nn放数字,无论什么操作,一定是1个操作符匹配2个数字,所以说,独立出来的运算函数一定是简单的,操作符栈顶弹1个,数字栈顶弹2个,算完了再压进去。
  • 如何维护括号的优先级,遇到左括号直接压栈,遇到右括号就一直操作直到左括号。这一步很关键,体现了“局部优先”的思想。
  • 最后将操作栈清空,剩下的数字栈的栈顶就是需要的数字。

    代码

    1. class Solution {
    2. public:
    3. void calcu(stack<char>& op, stack<int>& nn) {
    4. if (op.empty() || nn.empty()) {
    5. return;
    6. }
    7. char cur_op = op.top();
    8. op.pop();
    9. if (cur_op == '(') {
    10. return;
    11. }
    12. int num_behind = nn.top();
    13. nn.pop();
    14. int num_forward = nn.top();
    15. nn.pop();
    16. int res_num = 0;
    17. if (cur_op == '*') {
    18. res_num = num_forward * num_behind;
    19. } else if (cur_op == '+') {
    20. res_num = num_forward + num_behind;
    21. } else if (cur_op == '-') {
    22. res_num = num_forward - num_behind;
    23. } else if (cur_op == '/') {
    24. res_num = num_forward / num_behind;
    25. }
    26. nn.push(res_num);
    27. }
    28. int calculate(string s) {
    29. stack<char> op;
    30. stack<int> nn;
    31. map<char, int> h = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};
    32. int len_s = s.size();
    33. for (int i = 0; i < len_s; ++i) {
    34. if (s[i] == ' ') {
    35. continue;
    36. }
    37. if (isdigit(s[i])) {
    38. int j = i + 1, num = int (s[i] - '0');
    39. while (j < len_s && isdigit(s[j])) {
    40. num *= 10;
    41. num += int (s[j] - '0');
    42. j++;
    43. }
    44. nn.push(num);
    45. i = j - 1;
    46. } else if (s[i] == '(') {
    47. op.push(s[i]);
    48. } else if (s[i] == ')') {
    49. while (!op.empty() && op.top() != '(') {
    50. calcu(op, nn);
    51. }
    52. // 左括号也要出栈
    53. op.pop();
    54. } else {
    55. // 低优先级入栈需要先将高优先级弹栈
    56. while (!op.empty() && h[op.top()] >= h[s[i]]) {
    57. cout << s[i] << endl;
    58. calcu(op, nn);
    59. }
    60. op.push(s[i]);
    61. }
    62. }
    63. while (!op.empty()) {
    64. calcu(op, nn);
    65. }
    66. return nn.top();
    67. }
    68. };