leetcode
leetcode 2851 ~ 2900
计算器

计算器

难度:

标签:

题目描述

Given an arithmetic equation consisting of positive integers, +, -, * and / (no paren­theses), compute the result.

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

Example 1:

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

Example 2:

Input: " 3/2 "
Output: 1

Example 3:

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

Note:

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

代码结果

运行时间: 54 ms, 内存: 17.9 MB


/*
 * 思路:
 * 1. 使用栈来存储数字和计算结果。
 * 2. 使用变量来保存当前的数字和运算符。
 * 3. 遍历字符串,当遇到数字时,进行累加。
 * 4. 当遇到运算符时,根据上一个运算符和当前数字进行操作。
 * 5. '+' 和 '-' 将当前数字压入栈中('+' 直接压入,'-' 取负后压入)。
 * 6. '*' 和 '/' 取出栈顶数字进行运算后再压入。
 * 7. 最后将栈中的所有数字相加得到最终结果。
 */

import java.util.*;
import java.util.stream.Collectors;

public class Calculator {
    public int calculate(String s) {
        Stack<Integer> stack = new Stack<>();
        int num = 0;
        char sign = '+';
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (Character.isDigit(c)) {
                num = num * 10 + (c - '0');
            }
            if (!Character.isDigit(c) && c != ' ' || i == s.length() - 1) {
                if (sign == '+') {
                    stack.push(num);
                } else if (sign == '-') {
                    stack.push(-num);
                } else if (sign == '*') {
                    stack.push(stack.pop() * num);
                } else if (sign == '/') {
                    stack.push(stack.pop() / num);
                }
                sign = c;
                num = 0;
            }
        }
        return stack.stream().collect(Collectors.summingInt(Integer::intValue));
    }
}

解释

方法:

此题解采用了一个栈来处理没有括号的四则运算表达式。每次遇到运算符或者字符串的末尾时,根据前一个运算符来决定如何处理当前累积的数字。如果是加号或减号,将数字直接压入栈(减号则压入其负值)。对于乘号或除号,先从栈中弹出顶部数字,执行乘法或除法操作,然后将结果再压回栈中。最后,将栈中所有数字求和得到最终结果。这种方法有效地利用栈来处理运算符的优先级,避免了使用递归或额外的数据结构。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在处理表达式时,遇到运算符或字符串末尾才处理累积的数字的原因是什么?
在表达式处理过程中,数字可能由多个字符组成,所以需要一直读取字符直到遇到非数字字符(即运算符)或字符串结束,才能确定整个数字的值。此时,已经可以知道前一个运算符和当前完整的数字,便可以根据前一个运算符来正确处理这个数字(如直接压栈或与栈顶元素进行运算)。这种处理方式确保了在读取到运算符之前,数字的累积是完整且正确的。
🦆
为什么在处理乘除运算时,只从栈中弹出一个数字进行操作,而不是考虑连续的乘除运算如何处理?
在这个算法中,每次遇到乘除运算符时,从栈中弹出一个数字进行操作是因为乘法和除法具有左结合性,即它们会先与前一个数字(即栈顶元素)结合进行计算。这样处理可以立即解决当前运算符与前一个数字的运算问题,而不需要额外的逻辑来处理连续的乘除运算。连续的乘除操作会在遍历到各自的运算符时依次处理,因为每次处理都会将结果压回栈中,为下一个乘除运算做好准备。
🦆
在算法中,如何确保在处理除法时能够正确向下取整,尤其是在涉及负数时?
在Python中,整数除法`/`会得到浮点结果,而使用`int()`函数可以将浮点数向下取整到最接近的整数。特别是在涉及负数的除法时,Python的`int()`函数会将结果向零方向取整,这与一些其他语言中的行为不同。因此,在实现中,使用`int()`确保了即使在负数除法的情况下也能正确地向下取整。例如,`int(-3 / 2)`会得到`-1`,符合预期的结果。

相关问题