牛客 - HJ50 四则运算 - AC CODE

牛客 - HJ50 四则运算

牛客 - HJ50 四则运算

描述

对于输入的表达式,保证其形式合法,计算过程中全程合法,计算过程中不需要使用到实数。
结果 ans 在 [-1000, 1000] 范围内。
直接输出计算结果。

保证表达式字符串由 0-9 的数字、加法'+'、减法'-'、乘法'*'、除法'/'、小括号'()'、中括号'[]'、大括号'{}'组成,且运算符之间没有空格。

输入描述

输入一个长度在 [1, 1000] 范围、由题面所述符号构成的字符串,代表一个表达式。

输出描述

输出一个整数 ans,代表计算的答案,答案满足 [-1000, 1000] 范围

示例

输入

3+2*{1+2*[-4/(8-6)+7]}

输出

25

AC CODE

思路

  1. 第一个出现的数字和符号直接入栈
  2. 遇到数字直接入栈
  3. 遇到符号,先判断当前符号和栈顶符号的运算优先级,栈顶优先级更高,则取数字栈的2个栈顶运算;当前符号优先级更高则入栈
  4. 最后反复取数字栈的2个栈顶和符号栈栈顶运算,直到符号栈为空或只剩下一个数字

AC CODE

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class HJ50 {
    public static Integer Calculate(Character op, Integer a, Integer b) { // 运算函数
        if (op == '-') {
            return a - b;
        } else if (op == '+') {
            return a + b;
        } else if (op == '*') {
            return a * b;
        } else {
            return a / b;
        }
    }

    public static boolean ComparOpFirst(Character top, Character op) { // 符号优先级判断,当前符号优先级大于栈顶,返回true
        if (top == '(') { // '('的优先级最高
            return true;
        } else if (op == '+' || op == '-') { // + - 的优先级最低
            return false;
        } else if (op == '*' || op == '/') { // * / 的优先级只比'('低,'('后的第一个操作符一定会入栈,所以 * / 不会与'('比较
            return true;
        } else { // 默认true
            return true;
        }
    }

    public static void main(String[] args) {
        String strt = new String();
        try (Scanner scanner = new Scanner(System.in)) {
            strt = scanner.nextLine(); // 算式输入
        }
        // 输入数据处理,括号替换只是为了方便处理
        strt = strt.replace('{', '(');
        strt = strt.replace('}', ')');
        strt = strt.replace('[', '(');
        strt = strt.replace(']', ')');

        List<Integer> nums = new ArrayList<>(); // 数据栈
        List<Character> ops = new ArrayList<>(); // 符号栈

        boolean opFlag = true; // 第一个符号标记
        String data = new String(); // 数字str,使用String拼接数字,以便使用valueOf方法
        data = ""; // 初始化
        for (int h = 0; h < strt.length(); h++) {
            if (strt.charAt(h) >= '0' && strt.charAt(h) <= '9') { // 当前是数字时向后遍历,直到遍历出非数字
                while (h < strt.length() && strt.charAt(h) >= '0' && strt.charAt(h) <= '9') { // 数字识别
                    data += strt.charAt(h);
                    h++; // 此处直接h++遍历数字,后续被操作的就是符号
                }
                nums.add(Integer.valueOf(data)); // 数字入栈
                if (h >= strt.length()) { // 遍历到算式末尾了
                    break;
                }
            }

            if (strt.charAt(h) == '-') { // 减号特殊处理
                if (h == 0 || strt.charAt(h - 1) == '(') { // 表示负号,负号只出现在算式开头或'('之后,默认当算式中出现负数时,需要加小括号
                    data += strt.charAt(h);
                    continue; // 跳过,直接识别下一字符,下一字符一定是数字
                }
            }

            data = ""; // 数字重置,因为前面已经遍历到非数字位时才会停止,因此每次遍历完都要数字String重置

            if (opFlag) { // 第一个四则运算符还没入栈
                opFlag = false;
                ops.add(strt.charAt(h)); // 直接入栈
                continue; // 跳过
            }

            if (strt.charAt(h) == '(') {
                ops.add(strt.charAt(h)); // 左括号直接入栈
                opFlag = true; // 左括号入栈后,要重新入栈括号后第一次出现的操作符
                continue; // 跳过
            }

            if (strt.charAt(h) != ')') { // 遇到四则运算符
                if (ComparOpFirst(ops.get(ops.size() - 1), strt.charAt(h))) { // 操作符优先级高于栈顶
                    ops.add(strt.charAt(h)); // 入栈
                } else { // 栈顶优先级更高,需要运算栈顶
                    // 反复运算栈顶,直到栈空或者栈顶的优先级低于当前,只运算栈顶后就跳出,会有这种情况
                    // 比如出现 + / - 的操作组合,运算完 / 之后,运算完 + 才能运算 -
                    while (nums.size() >= 2 && ops.size() != 0
                            && (!ComparOpFirst(ops.get(ops.size() - 1), strt.charAt(h)))) {
                        // 取数字栈顶的两个元素
                        Integer b = nums.get(nums.size() - 1);
                        nums.remove(nums.size() - 1);
                        Integer a = nums.get(nums.size() - 1);
                        nums.remove(nums.size() - 1);
                        // 取符号栈顶
                        Character op = ops.get(ops.size() - 1);
                        ops.remove(ops.size() - 1);

                        Integer tAnser = Calculate(op, a, b); // 运算
                        nums.add(tAnser); // 结果入栈
                    }
                    ops.add(strt.charAt(h)); // 操作符入栈
                }
            }

            if (strt.charAt(h) == ')') { // 遇到')'则反复运算栈顶,直到遇到'('或者空栈
                while (nums.size() >= 2 && ops.size() != 0 && ops.get(ops.size() - 1) != '(') {
                    // 取数字栈顶的两个元素
                    Integer b = nums.get(nums.size() - 1);
                    nums.remove(nums.size() - 1);
                    Integer a = nums.get(nums.size() - 1);
                    nums.remove(nums.size() - 1);
                    // 取符号栈顶
                    Character op = ops.get(ops.size() - 1);
                    ops.remove(ops.size() - 1);

                    Integer tAnser = Calculate(op, a, b); // 运算
                    nums.add(tAnser); // 结果入栈
                }
                ops.remove(ops.size() - 1); // 左括号出栈
            }
        }

        while (nums.size() >= 2) { // 数字栈里面还有数字,则反复运算到只剩一个数字
            // 取数字栈顶的两个元素
            Integer b = nums.get(nums.size() - 1);
            nums.remove(nums.size() - 1);
            Integer a = nums.get(nums.size() - 1);
            nums.remove(nums.size() - 1);
            // 取符号栈顶
            Character op = ops.get(ops.size() - 1);
            ops.remove(ops.size() - 1);

            Integer tAnser = Calculate(op, a, b); // 运算
            nums.add(tAnser); // 结果入栈
        }

        System.out.println(nums.get(0));
    }
}

posted @   木槐muhuai  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示