牛客 - HJ50 四则运算
描述
对于输入的表达式,保证其形式合法,计算过程中全程合法,计算过程中不需要使用到实数。
结果 ans 在 [-1000, 1000]
范围内。
直接输出计算结果。
保证表达式字符串由 0-9 的数字、加法'+'、减法'-'、乘法'*'、除法'/'、小括号'()'、中括号'[]'、大括号'{}'组成,且运算符之间没有空格。
输入描述
输入一个长度在 [1, 1000]
范围、由题面所述符号构成的字符串,代表一个表达式。
输出描述
输出一个整数 ans,代表计算的答案,答案满足 [-1000, 1000]
范围
示例
输入
3+2*{1+2*[-4/(8-6)+7]}
输出
25
AC CODE
思路
- 第一个出现的数字和符号直接入栈
- 遇到数字直接入栈
- 遇到符号,先判断当前符号和栈顶符号的运算优先级,栈顶优先级更高,则取数字栈的2个栈顶运算;当前符号优先级更高则入栈
- 最后反复取数字栈的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) { // 符号优先级判断,当前符号优先级大于栈顶,返回trueif (top == '(') { // '('的优先级最高return true;} else if (op == '+' || op == '-') { // + - 的优先级最低return false;} else if (op == '*' || op == '/') { // * / 的优先级只比'('低,'('后的第一个操作符一定会入栈,所以 * / 不会与'('比较return true;} else { // 默认truereturn 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));}
}