借助栈实现表达式求值

表达式求值

http://www.nowcoder.com/questionTerminal/9566499a2e1546c0a257e885dfdbf30d

提交了7次才全部通过。。
代码还有很多可以优化的地方,如下,可能有考虑不全的情况,欢迎指正~

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String str = "";
        while ((str = reader.readLine()) != null){
            String pattern = "[^\\d|()()*+\\-/]";
            if (!Pattern.compile(pattern).matcher(str).find()){
                String[] expressions = str.split("");
                // 转换表达式
                final List<Object> suffix = infixToSuffix(expressions);
                // 计算结果
                System.out.println(evaluate(suffix));
            } else System.out.println(-1);
        }
        reader.close();
    }

    /**
     * 执行计算
     * @param suffix 后缀表达式
     * @return 返回Integer结果
     */
    public static Integer evaluate(List<Object> suffix){
        if (null == suffix || suffix.size() == 0) return -1;

        Stack<Integer> nums = new Stack<>(); // 存储数字

        for (int i = 0; i < suffix.size(); i++) {
            if (suffix.get(i) instanceof Integer) {
                // 遇到数字则入栈
                nums.push(Integer.parseInt(String.valueOf(suffix.get(i))));
            } else if (suffix.get(i) instanceof String && nums.size() >= 2){ // 遇到运算符,执行运算
                switch (String.valueOf(suffix.get(i))){
                    case "+":
                        nums.push(nums.pop() + nums.pop());
                        break;
                    case "-":
                        Integer pop1 = nums.pop();
                        Integer pop2 = nums.pop();
                        nums.push(pop2 - pop1);
                        break;
                    case "*":
                        nums.push(nums.pop() * nums.pop());
                        break;
                    case "/":
                        Integer denominator = nums.pop();
                        Integer numerator = nums.pop();
                        if (denominator == 0) return -1;
                        else nums.push(numerator / denominator);
                        break;
                }
            } else return -1;
        }
        Integer res = 0;
        while (!nums.isEmpty()) {
            res = nums.pop();
        }
        return res;
    }

    /**
     * 中缀表达式转后缀表达式(逆波兰表达式)
     * @param expressions 表达式字符串数组
     * @return 返回后缀表达式
     */
    public static List<Object> infixToSuffix(String[] expressions){
        if (null == expressions || expressions.length == 0) return null;

        Stack<String> stack = new Stack<>();
        StringBuilder builder = new StringBuilder();
        List<Object> result = new ArrayList<>();
        for (int i = 0; i < expressions.length; i++) {
            if (i == 0 && !Character.isDigit(expressions[0].charAt(0)) && 
                !expressions[0].equals("(") && !expressions[0].equals("(")){
                builder.append(expressions[0]);
                continue;
            }
            if (Character.isDigit(expressions[i].charAt(0))){
                // 遇到数字,拼接起来,还原原数
                builder.append(expressions[i]);
            } else {
                if (builder.length() != 0){
                    // 将还原后的数字存起来
                    result.add(Integer.parseInt(builder.toString()));
                    builder.delete(0, builder.length());
                }
                switch (expressions[i]){
                    case "+":
                    case "-":
                        if (expressions[i].equals("-") && i != 0 && (expressions[i - 1].equals("(") || expressions[i - 1].equals("(")))
                            builder.append(expressions[i]);
                        // +和-优先级相同且最低,当栈为空或栈顶元素为( 时直接入栈,注意,左括号只有遇到右括号才执行出栈
                        else if (stack.isEmpty() || stack.peek().equals("(") || stack.peek().equals("("))
                            stack.push(expressions[i]);
                        else {
                            // 当栈不为空且栈顶元素不是左括号时,将栈元素依次输出,直到栈为空,再压入当前运算符
                            while (!stack.isEmpty() && !stack.peek().equals("(") && !stack.peek().equals("("))
                                result.add(stack.pop());
                            stack.push(expressions[i]);
                        }
                        break;
                    case "*":
                    case "/":
                        // *和/优先级相同且大于+和-,小于括号,当栈为空或栈顶元素为( 时直接入栈,注意,左括号只有遇到右括号才执行出栈
                        if (stack.isEmpty() || stack.peek().equals("(") || stack.peek().equals("("))
                            stack.push(expressions[i]);
                        else {
                            // 当栈不为空且栈顶元素不是左括号,同时栈顶元素优先级大于等于自己时,将栈元素依次输出,直到栈为空,再压入当前运算符
                            while (!stack.isEmpty() && !stack.peek().equals("+") && !stack.peek().equals("-")
                                    && !stack.peek().equals("(") && !stack.peek().equals("("))
                                result.add(stack.pop());
                            stack.push(expressions[i]);
                        }
                        break;
                    case "(":
                    case "(":
                        // 遇到左括号直接入栈
                        stack.push(expressions[i]);
                        break;
                    case ")":
                    case ")":
                        // 遇到右括号,当栈不为空且栈顶元素不是左括号时,输出栈元素,直到栈为空或者遇到了左括号。注意这里不执行入栈操作
                        while (!stack.isEmpty() && !stack.peek().equals("(") && !stack.peek().equals("("))
                            result.add(stack.pop());
                        // 因为遇到左括号而停止出栈时,需要将左括号出栈
                        if (!stack.isEmpty())
                            stack.pop();
                        break;
                }
            }
        }
        // 先清空builder
        if (builder.length() != 0){
            result.add(Integer.parseInt(builder.toString()));
            builder.delete(0, builder.length());
        }
        // 最后一步,将栈中剩余元素全部输出
        while (!stack.isEmpty())
            result.add(stack.pop());
        return result;
    }
}
全部评论
可是牛客网上给的难度是简单啊,有没有现成的java方法能直接调?
点赞 回复 分享
发布于 2022-02-27 19:17

相关推荐

评论
3
2
分享

创作者周榜

更多
牛客网
牛客企业服务