题目
示例1
输入:
1 + 5 * 7 / 8
输出:
43/8
示例2
输入:
1 / (0 - 5)
输出:
-1/5
说明:负号需要提到最前面
示例3
输入:
1 * (3 * 4 / (8 - (7 + 0)))
输出:
12
说明:注意括号可以多重嵌套
解题思路
1.处理空格:首先,去除输入表达式中的空格。
2.转换为逆波兰表达式:利用栈来将中缀表达式转换为逆波兰表达式。这可以通过遍历输入表达式的每个元素来实现。遇到数字直接输出,遇到运算符则比较其优先级与栈顶运算符的优先级,按照一定规则进行出栈和入栈操作。具体规则可以参考算法导论中关于中缀表达式转换为逆波兰表达式的算法。
3.计算逆波兰表达式:利用栈来计算逆波兰表达式。
遍历逆波兰表达式的每个元素,遇到数字则入栈,遇到运算符则从栈中弹出足够的操作数进行运算,再将结果入栈。重复此过程直到表达式结束。
4. 处理分数:在计算过程中,需要考虑分数的表示和简化。可以使用一个结构体或类来表示分数,其中包含分子和分母两个整数。每次运算后,检查结果是否为整数,如果是整数则直接输出,如果是分数则对分数进行化简。
5.异常处理:在计算过程中,需要检查除数是否为0。如果遇到除数为0的情况,直接输出"ERROR"
题解
优化之后:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
/**
* @Author:
* @Create: 2024-10-01 13:51
* @Description:
*/
public class 给定一个表达式2 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String infix = in.nextLine().replace(" ", "");
List<String> suffix = changeToSuffix(infix);
try {
Num num = calculateSuffix(suffix);
System.out.println(num.getResult(num));
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
}
private static Num calculateSuffix(List<String> suffix) {
Stack<Num> nums = new Stack<>();
Num res = new Num(0, 1);
for (String s : suffix) {
if (s.matches("\\d+")) {
nums.push(new Num(Integer.parseInt(s), 1));
} else {
Num num1 = nums.pop();
Num num2 = nums.pop();
if ("*".equals(s)) {
res = num2.mul(num1);
} else if ("/".equals(s)) {
res = num2.div(num1);
} else if ("+".equals(s)) {
res = num2.add(num1);
} else if ("-".equals(s)) {
res = num2.sub(num1);
} else {
throw new ArithmeticException("运算符有误");
}
nums.push(res);
}
}
return res;
}
private static List<String> changeToSuffix(String infix) {
Stack<String> oper = new Stack<>();
ArrayList<String> res = new ArrayList<>();
int len = infix.length();
for (int i = 0; i < len; i++) {
char c = infix.charAt(i);
if (Character.isDigit(c)) {
int j = i;
while (j < len && Character.isDigit(infix.charAt(j))) {
j++;
}
res.add(infix.substring(i, j));
i = --j;
} else if (c == '(') {
oper.push(c + "");
} else if (c == ')') {
while (!oper.isEmpty() && !"(".equals(oper.peek())) {
res.add(oper.pop());
}
oper.pop();
} else {
while (!oper.isEmpty() && getPriority(c + "") <= getPriority(oper.peek())) {
res.add(oper.pop());
}
oper.push(c + "");
}
}
while (!oper.isEmpty()) {
res.add(oper.pop());
}
return res;
}
private static int getPriority(String operator) {
if ("*".equals(operator) || "/".equals(operator)) return 2;
else if ("+".equals(operator) || "-".equals(operator)) return 1;
else return 0;
}
static class Num {
int x;
int y;
public Num(int x, int y) {
this.x = x;
this.y = y;
}
private Num mul(Num num) {
return new Num(this.x * num.x, this.y * num.y);
}
private Num div(Num num) {
if (num.x == 0) {
throw new ArithmeticException("ERROR");
}
return new Num(this.x * num.y, this.y * num.x);
}
private Num add(Num num) {
return new Num(this.x * num.y + this.y * num.x, this.y * num.y);
}
private Num sub(Num num) {
return new Num(this.x * num.y - this.y * num.x, this.y * num.y);
}
private int gcd(int a, int b) {
return a % b == 0 ? b : gcd(b, a % b);
}
private String getResult(Num num) {
int xy_gcd = gcd(num.x, num.y);
int x = num.x / xy_gcd;
int y = num.y / xy_gcd;
if (x * y < 0) {
x = -Math.abs(x);
y = Math.abs(y);
}
return x % y == 0 ? x / y + "" : x + "/" + y;
}
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String expression = in.nextLine();
List<String> infixExpressList = toInfixExpressList(expression);
List<String> suffixExpressionList = parseSuffixExpressionList(infixExpressList);
try {
System.out.println(calculate(suffixExpressionList));
} catch (Exception e) {
System.out.println("ERROR");
}
}
private static String calculate(List<String> list) {
Stack<Num> stack = new Stack<>();
for (String item : list) {
if (item.matches("\\d+")) {
stack.push(new Num(Integer.parseInt(item)));
} else {
Num num2 = stack.pop();
Num num1 = stack.pop();
Num res = new Num(0);
switch (item) {
case "+":
add(res, num1, num2);
break;
case "-":
sub(res, num1, num2);
break;
case "*":
multi(res, num1, num2);
break;
case "/":
div(res, num1, num2);
break;
default:
break;
}
stack.push(res);
}
}
return getRes(stack.pop());
}
private static String getRes(Num res) {
int x = res.x;
int y = res.y;
if (x * y < 0) {
x = -Math.abs(x);
y = Math.abs(y);
}
return x % y == 0 ? x / y + "" : x + "/" + y;
}
private static void div(Num res, Num num1, Num num2) {
if (num2.x == 0) {
throw new RuntimeException();
}
res.x = num1.x * num2.y;
res.y = num1.y * num2.x;
simplify(res);
}
private static void multi(Num res, Num num1, Num num2) {
res.x = num1.x * num2.x;
res.y = num1.y * num2.y;
simplify(res);
}
private static void add(Num res, Num num1, Num num2) {
res.x = num1.x * num2.y + num1.y * num2.x;
res.y = num1.y * num2.y;
simplify(res);
}
private static void sub(Num res, Num num1, Num num2) {
res.x = num1.x * num2.y - num1.y * num2.x;
res.y = num1.y * num2.y;
simplify(res);
}
private static void simplify(Num res) {
int xyGcd = gcd(res.x, res.y);
res.x /= xyGcd;
res.y /= xyGcd;
}
private static List<String> parseSuffixExpressionList(List<String> list) {
Stack<String> s1 = new Stack<>();
List<String> s2 = new ArrayList<>();
for (String item : list) {
if (item.matches("\\d+")) {
s2.add(item);
} else if (item.equals("(")) {
s1.push(item);
} else if (item.equals(")")) {
while (!s1.peek().equals("(")) {
s2.add(s1.pop());
}
s1.pop();
} else { // 运算符
while (!s1.isEmpty() && getPriority(item) <= getPriority(s1.peek())) {
s2.add(s1.pop());
}
s1.push(item);
}
}
// s1剩余-->s2
while (!s1.isEmpty()) {
s2.add(s1.pop());
}
return s2;
}
private static List<String> toInfixExpressList(String s) {
List<String> res = new ArrayList<>();
int i = 0;
while (i < s.length()) {
if (' ' == s.charAt(i)) {
i++;
} else if (!Character.isDigit(s.charAt(i))) {
res.add(s.charAt(i) + "");
i++;
} else {
StringBuilder str = new StringBuilder();
while (i < s.length() && Character.isDigit(s.charAt(i))) {
str.append(s.charAt(i));
i++;
}
res.add(str.toString());
}
}
return res;
}
// 最大公约数
public static int gcd(int a, int b) {
return (a % b == 0) ? b : gcd(b, a % b);
}
public static int getPriority(String input) {
if (input.equals("*") || input.equals("/")) {
return 2;
} else if (input.equals("+") || input.equals("-")) {
return 1;
} else {
return 0;
}
}
static class Num {
int x;
int y = 1;
public Num(int x) {
this.x = x;
}
}
}
参考
存在问题
import java.util.Scanner;
import java.util.Stack;
public class 给定一个表达式 {
public static Stack<Integer[]> nums;
public static Stack<Character> operations;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String input_str1 = in.nextLine();
nums = new Stack<>();
operations = new Stack<>();
int length = input_str1.length();
char[] input_str = input_str1.toCharArray();
String current = "";
int i = 0;
while (i < length) {
if (Character.isDigit(input_str[i])) {
while (true) {
if (!Character.isDigit(input_str[i])) {
break;
}
current += input_str[i];
if (i + 1 >= length) {
break;
}
i += 1;
}
nums.push(new Integer[]{1, Integer.parseInt(current)});
current = "";
} else if (input_str[i] == '(') {
operations.push(input_str[i]);
} else if (input_str[i] == ')') {
while (operations.peek() != '(') {
eval();
}
operations.pop();
} else if (input_str[i] == ' ') {
i += 1;
continue;
} else {
while (!operations.isEmpty() && operations.peek() != '('
&& get_priority(input_str[i]) <= get_priority(operations.peek())) {
eval();
}
operations.push(input_str[i]);
}
i++;
}
while (true) {
if (nums.size() <= 1) {
break;
} else {
eval();
}
}
Integer[] result = nums.peek();
if (result[0] == 0) {
System.out.println("ERROR");
} else {
int up = gcd(result[0], result[1]);
result[0] /= up;
result[1] /= up;
if (result[0] * result[1] < 0) {
System.out.print("-");
}
if (Math.abs(result[0]) == 1) {
System.out.println(result[1]);
} else {
System.out.println(Math.abs(result[1]) + "/" + Math.abs(result[0]));
}
}
}
// 最大公约数
public static int gcd(int a, int b) {
return (a % b == 0) ? b : gcd(b, a % b);
}
public static void eval() {
Integer[] nums1 = nums.pop();
Integer[] nums2 = nums.pop();
char x = operations.pop();
Integer[] result = new Integer[2];
if (x == '*' || x == '+' || x == '-') {
result[0] = nums2[0] * nums1[0];
} else {
result[0] = nums2[0] * nums1[1];
}
int sum_a = nums2[1] * nums1[0];
int sum_b = nums1[1] * nums2[0];
if (x == '*') {
result[1] = nums2[1] * nums1[1];
} else if (x == '+') {
result[1] = sum_a + sum_b;
} else if (x == '-') {
result[1] = sum_a - sum_b;
} else {
result[1] = nums2[1] * nums1[0];
}
nums.push(result);
}
public static int[] split(String input_str, String chars) {
String[] tmp2 = input_str.split(chars);
int[] results = new int[tmp2.length];
for (int i = 0; i < tmp2.length; i++) {
results[i] = Integer.parseInt(tmp2[i]);
}
return results;
}
public static int get_priority(Character input) {
if (input == '+' || input == '-') {
return 0;
} else {
return 1;
}
}
}