题目

Implement a basic calculator to evaluate a simple expression string.

The expression string contains only non-negative integers, +, -, *, / operators and empty spaces ``. The integer division should truncate toward zero.

Example 1:

  1. Input: "3+2*2"
  2. Output: 7

Example 2:

  1. Input: " 3/2 "
  2. Output: 1

Example 3:

  1. Input: " 3+5 / 2 "
  2. Output: 5

Note:

  • You may assume that the given expression is always valid.
  • Do not use the eval built-in library function.

题意

计算只包含+, -, *, /和空格的数学表达式的值。

思路

方法一:从后向前遍历字符串,遇空格跳过,遇*, /压入操作符栈中,遇数字压入操作数栈中,遇’+’, ‘-‘需要进行判断:如果操作符栈栈顶为*/,则从操作数栈和操作符栈分别出栈,将计算结果压回操作数栈,重复上述过程直到操作符栈为空或其栈顶为+, -,再将当前的+, -压入操作符栈中;其余情况则直接将+, -压入操作符栈中。全部遍历完后,重复出栈操作数栈和操作符栈计算结果即可。

方法二:从前向后遍历,参考自 [LeetCode] 227. Basic Calculator II 基本计算器之二


代码实现

Java

从后向前遍历

  1. class Solution {
  2. public int calculate(String s) {
  3. Deque<Integer> nums = new ArrayDeque<>();
  4. Deque<Character> ops = new ArrayDeque<>();
  5. for (int i = s.length() - 1; i >= 0; i--) {
  6. char c = s.charAt(i);
  7. if (c == ' ') {
  8. continue;
  9. } else if (c == '+' || c == '-') {
  10. while (!ops.isEmpty() && (ops.peek() == '*' || ops.peek() == '/')) {
  11. int a = nums.pop();
  12. int b = nums.pop();
  13. char op = ops.pop();
  14. int cal = op == '*' ? a * b : a / b;
  15. nums.push(cal);
  16. }
  17. ops.push(c);
  18. } else if (c == '*' || c == '/') {
  19. ops.push(c);
  20. } else {
  21. int num = c - '0';
  22. int zeros = 10;
  23. while (i - 1 >= 0 && s.charAt(i - 1) <= '9' && s.charAt(i - 1) >= '0') {
  24. num = (s.charAt(i - 1) - '0') * zeros + num;
  25. zeros *= 10;
  26. i--;
  27. }
  28. nums.push(num);
  29. }
  30. }
  31. while (nums.size() != 1) {
  32. int a = nums.pop();
  33. int b = nums.pop();
  34. char op = ops.pop();
  35. int cal = (op == '+' ? a + b : op == '-' ? a - b : op == '*' ? a * b : a / b);
  36. nums.push(cal);
  37. }
  38. return nums.pop();
  39. }
  40. }

从前向后遍历

  1. class Solution {
  2. public int calculate(String s) {
  3. Deque<Integer> stack = new ArrayDeque<>();
  4. int factor = 1;
  5. for (int i = 0; i < s.length(); i++) {
  6. char c = s.charAt(i);
  7. if (c == ' ') {
  8. continue;
  9. } else if (c == '*' || c == '/') {
  10. int a = stack.pop();
  11. int b = 0;
  12. while (!(s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '9')) {
  13. i++;
  14. }
  15. while (i + 1 < s.length() && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '9') {
  16. b = b * 10 + s.charAt(i + 1) - '0';
  17. i++;
  18. }
  19. stack.push(c == '*' ? a * b : a / b);
  20. } else if (c == '+' || c == '-') {
  21. factor = c == '+' ? 1 : -1;
  22. } else {
  23. int num = c - '0';
  24. while (i + 1 < s.length() && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '9') {
  25. num = num * 10 + s.charAt(i + 1) - '0';
  26. i++;
  27. }
  28. stack.push(num * factor);
  29. }
  30. }
  31. while (stack.size() != 1) {
  32. stack.push(stack.pop() + stack.pop());
  33. }
  34. return stack.pop();
  35. }
  36. }

JavaScript

  1. /**
  2. * @param {string} s
  3. * @return {number}
  4. */
  5. var calculate = function (s) {
  6. let nums = []
  7. let op = 1
  8. let i = 0
  9. let reg = /[0-9]/
  10. while (i < s.length) {
  11. if (reg.test(s[i])) {
  12. let num = parseInt(s[i])
  13. while (++i < s.length && reg.test(s[i])) {
  14. num = num * 10 + parseInt(s[i])
  15. }
  16. nums.push(op * num)
  17. } else if (s[i] === '+' || s[i] === '-') {
  18. op = s[i++] === '+' ? 1 : -1
  19. } else if (s[i] === '*' || s[i] === '/') {
  20. let c = s[i]
  21. let A = nums.pop()
  22. while (s[++i] === ' ') {}
  23. let B = parseInt(s[i])
  24. while (++i < s.length && reg.test(s[i])) {
  25. B = B * 10 + parseInt(s[i])
  26. }
  27. nums.push(c === '*' ? A * B : Math.trunc(A / B))
  28. } else {
  29. i++
  30. }
  31. }
  32. return nums.reduce((acc, cur) => acc + cur)
  33. }