算法通关村第四关——黄金挑战之计算器问题的分析

29 阅读2分钟

1.计算器问题

对应leetcode227. 基本计算器 II - 力扣(LeetCode)](leetcode.cn/problems/ba…)

image.png

解题思路:

就拿 s = "3+2*2" 这个例子来说:首先我们应该要明确的是即使+ - 运算符出现在字符串的前面,但如果存在 *,/ 运算时,乘除运算一定要优先进行;这才是符合正常的数学表达式的运算逻辑;那么我们应该怎么处理才能做到这一点呢?

数据结构栈就可以实现该效果,如果我们把 ' * ' 号前面的所有数字全部依次入栈,此时栈顶元素为 2 ,那么当字符串遍历到第二个2时,只要和当前栈顶元素相乘再共同入栈,保证最后只要正常累加栈中元素即可实现计算器的效果;

画个图来解释效果更佳:

初始过程:preSign用来记录当前遍历到的字符的前一个运算符是哪个,默认为' + ';

num 用来记录需要入栈的数值;

stack 初始为空栈;

image.png

中间过程:当 i >=0 && i<=charArr.length-1时

image.png

image.png

当 i 来到数组最后一个位置时

image.png

image.png

代码如下:

public static int calculate(String str) {
    Stack<Integer> stack = new Stack<>();
    char[] charArr = str.toCharArray();
    // 记录上一个符号 ,初始化为'+';
    char preSign = '+';
    int num = 0; //定义存入栈中的各个整数
    for (int i = 0; i < charArr.length; i++) {
        if (Character.isDigit(charArr[i])) {
            // 如果字符串是  "5+105",如果遍历到"105" 位置时,能让105整体入栈
            num = num * 10 + charArr[i] - '0';
        }
        if (!Character.isDigit(charArr[i]) && charArr[i] != ' ' || i == charArr.length - 1) {
            switch (preSign) {
                case '+':
                    stack.push(num);
                    break;
                case '-':
                    stack.push(-num);
                    break;
                case '*':
                    stack.push(stack.pop() * num);
                    break;
                default:
                    stack.push(stack.pop() / num);
            }
            // 将当前运算符赋值给preSign;这样当又来到一个新的位置时,保证preSign一直记录的时新位置的前一个
            preSign = charArr[i];
            // 要将num重新赋值为0,防止重复计算
            num = 0;
        }
    }
    // 定义返回的结果
    int sum = 0;
    // 累加栈中的元素,即可得到返回结果
    while (!stack.isEmpty()) {
        sum += stack.pop();
    }
    return sum;
}

总的来说这道题目如果要完全通过的话还是要花很多功夫的;需要考虑的点还是很多的,比如说1. 遍历到最后一个位置时,同样需要进行入栈操作;2. 运算符为 +,- 时,该怎么进行入栈操作,运算符为 * , / 时,又该怎么进行入栈操作; 3. num = num * 10 + charArr[i] - '0'这一行代码该怎么理解等等;