1 思路如下

  1. 通过一个index索引值来 遍历算式表达式;

  2. 使用两个栈来模拟。一个为数字栈,一个为符号栈;

  3. 如果为数字,则入数字栈;

  4. 如果为符号,则分以下情况:

    4.1 符号栈为空:直接入符号栈;

    4.2 符号栈不为空:将当前符号与符号栈中的栈顶元素进行优先级比较。 如果当前操作符号优先级小于栈顶元素,则取出符号栈的栈顶元素,并从数字栈取出两个数进行运算,得到数字结果入数字栈,并将当前操作符入符号栈。如果当前的操作符的优先级大于符号栈栈顶元素,则直接入符号栈。

  5. 当表达式扫描完毕,则顺序从数字栈和符号栈取出对应的数字和符号进行计算,将结果继续存入数字栈,直到符号栈为空;

  6. 此时,数字栈只剩下了计算的结果, 该结果即为表达式的值。

栈的内容可以参考我的博客链接:Java数据结构:栈与综合计算器的实现(图解+完整代码)

以3+2*6-2为例:

  • 先将3入数字栈

在这里插入图片描述

  • + 入符号栈

在这里插入图片描述

  • 2入数字栈

在这里插入图片描述

  • 遇到了 *,将其与符号栈的栈顶元素 + 比较,* 的优先级更高,因此,* 直接入符号栈

在这里插入图片描述

  • 6 入数字栈

在这里插入图片描述

  • - 与符号栈栈顶 * 进行比较,-优先级低,因此,将符号栈的栈顶 * 出栈。数字栈依次出栈两个数6、2,计算2*6的值为12,并将12入数字栈,当前操作符- 入符号栈

在这里插入图片描述

  • 2 入栈,至此,表达式遍历完成。下面将要开始依次取值计算,直到符号栈为空。

在这里插入图片描述

  • 将2、12从数字栈取出,将-从符号栈取出,计算12-2的值10,入数字栈

在这里插入图片描述

  • 依次将10、3从数字栈出栈,+从符号栈取出,并计算3+10的值为13,13入数字栈。此时,符号栈为空,运算到此为止,13即为表达式的结果。

在这里插入图片描述

2 注意事项

需要考虑括号,当符号栈为空或者栈顶为左括号的时候,符号直接入栈。当当前的元素为右括号的时候,需要依次将符号从符号栈中弹出,进行对应数字栈的计算,将计算结果压入数字栈。 直到遇到左括号为止,将左括号出栈。

3 完整代码

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回表达式的值
     * @param s string字符串 待计算的表达式
     * @return int整型
     */
    public int solve (String s) {
        // write code here
        //利用双栈去模拟,一个数字栈,一个符号栈
        int res = 0; //存储结果
        Stack<String> numStack = new Stack<>();
        Stack<String> operationStack = new Stack<>();
        //获取表达式的list
        List<String> list = toInfixExpressionList(s);
        //遍历list
        String str = "";
        for(int i = 0; i < list.size(); i++){
            //如果是数字则入数字栈
            str = list.get(i);
            if(str.matches("\\d+")){
                numStack.push(str);
            }else{
                //如果是符号,则入符号栈
                //对于左括号,直接入符号栈
                if(operationStack.isEmpty() || str.equals("(")){
                    operationStack.push(str);
                }else if(str.equals(")")){
                    //如果是右括号,则依次弹出操作符,并从数栈弹出两个数进行计算,后压栈
                    while(!operationStack.peek().equals("(")){
                        String operation = operationStack.pop();
                        int num1 = Integer.valueOf(numStack.pop());
                        int num2 = Integer.valueOf(numStack.pop());
                        res = calculate(num1, num2, operation);
                        numStack.push(String.valueOf(res));
                    }
                    //将匹配的左括号出栈
                    operationStack.pop();
                }else{
                    //如果是符号,则将当前符号与符号栈栈顶元素进行判断
                    //如果优先级小于等于栈顶元素,则出栈运算符,并取出两个数进行计算,压栈
                    if ((!operationStack.peek().equals("(") && !operationStack.peek().equals(")"))
                            && priority(str) <= priority(operationStack.peek())){
                        int num1 = Integer.parseInt(numStack.pop());
                        int num2 = Integer.parseInt(numStack.pop());
                        String oper = operationStack.pop();
                        res = calculate(num1, num2, oper);
                        //将运算结果入数栈
                        numStack.push(String.valueOf(res));
                        //将当前的操作符入符号栈
                        operationStack.push(str);
                    }else {
                        //栈顶元素优先级小于当前运算符,或者为括号
                        operationStack.push(str);
                    }
                }
            }
        }
        //表达式扫描完毕过后,顺序的从数栈和符号栈取出对应的数字和符号进行运算
        //最后数栈只剩的一个数字为结果
        //也可以判断符号栈是否为空,如果为空则说明数栈只剩一个数
        while (numStack.size() > 1){
            int num1 = Integer.parseInt(numStack.pop());
            int num2 = Integer.parseInt(numStack.pop());
            String oper = operationStack.pop();
            res = calculate(num1, num2, oper);
            numStack.push(String.valueOf(res));
        }
        //打印结果
        return Integer.valueOf(numStack.pop());
    }

    //返回运算符号的优先级,返回数字越大,优先级越大
    public int priority(String operation){
        if ("*".equals(operation) || "/".equals(operation)){
            return 1;
        }else if ("-".equals(operation) || "+".equals(operation)){
            return 0;
        }else {
            return -1;
        }
    }

    //将中缀表达式分数字和运算符依次存入List中,便于遍历
    public List<String> toInfixExpressionList(String s){
        List<String> list = new ArrayList<>();
        char c = ' ';//存储每一位String字符
        for(int i = 0; i < s.length(); ){
            if((c=s.charAt(i)) < '0' || (c=s.charAt(i)) > '9'){//是运算符的情况
                list.add(c+"");
                i++;
            }else{
                //数字处理拼接
                String str = "";
                while(i < s.length() && (c=s.charAt(i)) >= '0' && (c=s.charAt(i)) <= '9'){
                    str += c;
                    i++;
                }
                list.add(str);
            }
        }
        return list;
    }

    //四则运算
    public int calculate(int num1, int num2, String operation){
        int res = 0;
        switch(operation){
            case "+":
                res = num2 + num1;
                break;
            case "-":
                res = num2 - num1;
                break;
            case "*":
                res = num2 * num1;
                break;
            case "/":
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
}

alt