题解 | #表达式求值#

表达式求值

https://www.nowcoder.com/practice/9566499a2e1546c0a257e885dfdbf30d

import java.util.Scanner;
import java.util.Stack;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextLine()) {
            String expression = in.nextLine();
            StringBuilder postfixExpression = getPostfixExpression(expression);
            String result = getResult(postfixExpression);
            System.out.println(result);
        }
    }
     private static String getResult(StringBuilder postfixExpression) {
        Stack<String> executeStack = new Stack<>();
        //暂存数字
        StringBuilder tip = new StringBuilder();
        for (int i = 0, len = postfixExpression.length(); i < len; i++) {
            char tmp = postfixExpression.charAt(i);
            //下面的判断中不用加上是否等于'.' 因为数字不会以.开头
            //(tmp=='-'||tmp=='+')&&i<len-1&&postfixExpression.charAt(i+1)=='#' 是为了兼容正负号
            if (((tmp >= '0') && (tmp <= '9')) || (tmp == '-' || tmp == '+') && i < len - 1 && postfixExpression.charAt(i + 1) == '#') {
                int j = i;
                while (j < len - 1) {
                    //tmp=postfixExpression.charAt(j) 这样赋值是为了避免正负号被当成运算符号,所以将正负数的最后一位当做tmp值
                    tip.append(tmp = postfixExpression.charAt(j));
                    if (postfixExpression.charAt(j + 1) == '#') {
                        //+2是因为隔了个#
                        j = j + 2;
                    } else {
                        break;
                    }
                }
                executeStack.push(tip.toString());
                //清除缓存
                tip.setLength(0);
                //将游标设置到准确位置上
                i = j;
            }
            //因为栈的特性先弹出的是运算符后面的数字所以要注意顺序
            if (tmp == '+') {
                Integer a = Integer.valueOf(executeStack.pop());
                Integer b = Integer.valueOf(executeStack.pop());
                executeStack.push(String.valueOf(b + a));
            }
            if (tmp == '-') {
                Integer a = Integer.valueOf(executeStack.pop());
                Integer b = Integer.valueOf(executeStack.pop());
                executeStack.push(String.valueOf(b - a));
            }
            if (tmp == '*') {
                Integer a = Integer.valueOf(executeStack.pop());
                Integer b = Integer.valueOf(executeStack.pop());
                executeStack.push(String.valueOf(b * a));
            }
            if (tmp == '/') {
                Integer a = Integer.valueOf(executeStack.pop());
                Integer b = Integer.valueOf(executeStack.pop());
                executeStack.push(String.valueOf(b / a));
            }

        }
        String result = executeStack.pop();
        return Float.valueOf(result).intValue()+"";
    }


    private static StringBuilder getPostfixExpression(String expression) {
        //清空空格
        expression = expression.replaceAll(" ", "");
        //表达式缓存
        StringBuilder postfixExpression = new StringBuilder();
        //运算符栈
        Stack<Character> operatorStack = new Stack<>();
        boolean isnum = false;
        for (int i = 0; i < expression.length(); i++) {
            char cur = expression.charAt(i);
            //多位数字或小数数字用#链接
            if (((cur >= '0') && (cur <= '9')) || (cur == '.')) {
                if (isnum) {
                    postfixExpression.append("#");
                }
                postfixExpression.append(expression.charAt(i));
                isnum = true;
                continue;
            } else {
                //兼容数字前的正负标志
                if (cur == '-' || cur == '+') {
                    //游标在刚开始或者前一位是左括号的时候就是正负号
                    if (i == 0 || expression.charAt(i - 1) == '(' || expression.charAt(i - 1) == '[') {
                        postfixExpression.append(expression.charAt(i));
                        isnum = true;
                        continue;
                    }
                }
                isnum = false;
            }

            switch (cur) {
                case '[':
                case '(':
                    //左括号无脑压入栈
                    operatorStack.push(cur);
                    break;
                case ')': {
                        //遇到右括号在碰到左括号前无脑出栈
                    while (!operatorStack.empty()) {
                        if (operatorStack.peek() == '(') {
                            operatorStack.pop();
                            break;
                        } else {
                            postfixExpression.append(operatorStack.pop());
                        }
                    }
                    break;
                }
                case ']': {
                    //遇到右括号在碰到左括号前无脑出栈
                    while (!operatorStack.empty()) {
                        if (operatorStack.peek() == '[') {
                            operatorStack.pop();
                            break;
                        } else {
                            postfixExpression.append(operatorStack.pop());
                        }
                    }
                    break;

                }
                case '+':
                case '-':
                    //栈为空直接压入
                    if (operatorStack.isEmpty()) {
                        operatorStack.push(cur);
                        break;
                    }
                    Character peek1 = operatorStack.peek();
                    //栈顶元素为左括号则压入
                    if (peek1 == '[' || peek1 == '(') {
                        operatorStack.push(cur);
                        break;
                    }
                    if (peek1 == '/' || peek1 == '*') {
                        //栈顶元素为乘除将栈顶元素弹出到表达式
                        postfixExpression.append(operatorStack.pop());
                        //当前运算符号为加减,运算符栈不为空的情况下依次比较元素(实际上就是直接弹出栈结束或者遇到左括号终止)
                        while (!operatorStack.isEmpty()) {
                            if (operatorStack.peek() == '(' || operatorStack.peek() == '[') {
                                break;
                            }
                            postfixExpression.append(operatorStack.pop());
                        }
                        operatorStack.push(cur);
                        break;
                    }
                    if (peek1 == '+' || peek1 == '-') {
                        //栈顶元素为加减 则弹出栈顶压入当前操作符
                        postfixExpression.append(operatorStack.pop());
                        operatorStack.push(cur);
                        break;
                    }
                case '*':
                case '/':
                    //栈为空直接压入
                    if (operatorStack.empty()) {
                        operatorStack.push(cur);
                        break;
                    }
                    Character peek = operatorStack.peek();
                    //栈顶元素为左括号或者加减则压入
                    if (peek == '+' || peek == '-'||peek == '('||peek=='[') {
                        operatorStack.push(cur);
                        break;
                    }
                    //栈顶为乘除的时候压入
                    if (peek == '*' || peek == '/') {
                        postfixExpression.append(operatorStack.pop());
                        operatorStack.push(cur);
                    }
                    break;
            }
        }
        //中缀表达式循环结束,表达式栈还有操作符全部按顺序压入后缀表达式
        while (!operatorStack.isEmpty()) {
            postfixExpression.append(operatorStack.pop());
        }
        return postfixExpression;
    }
}

#栈的压入、弹出序列#
全部评论

相关推荐

绝迹的星:前端和后端写两份简历, 如果想干全栈就直接写求职意向为全栈工程师
点赞 评论 收藏
分享
想按时下班的大菠萝在...:隔壁学校的,加油多投, 实在不好找可以下个学期开学找,把算法八股准备好,项目有空再换换
投了多少份简历才上岸
点赞 评论 收藏
分享
昨天 15:02
门头沟学院 Java
刚打开网申页面就不想填了,还是不要为难自己了
poppinzhan...:多益老行业毒瘤了,碰到徐波这种恶心的烂人,去了也是受罪。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务