简单四则运算解析器问题| 豆包MarsCode AI刷题

215 阅读3分钟

问题描述

小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符+、-及括号()。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。

问题理解

我们需要实现一个基本的计算器来计算简单的字符串表达式的值。表达式可能包含数字(0-9)、运算符+、-、、/及括号()。除法运算应只保留整数结果。 数据结构选择 栈(Stack):我们使用两个栈,一个用于存储数字(numStack),另一个用于存储运算符(opStack)。栈的特性(后进先出)非常适合处理表达式中的运算符优先级和括号。 算法步骤 遍历表达式:从左到右遍历表达式中的每个字符。 处理数字:如果当前字符是数字,则继续读取后续的数字字符,直到遇到非数字字符,然后将完整的数字压入numStack。 处理左括号:如果当前字符是左括号(,则将其压入opStack。 处理右括号:如果当前字符是右括号),则从opStack中弹出运算符并从numStack中弹出两个数字进行计算,直到遇到左括号(。 处理运算符:如果当前字符是运算符(+、-、、/),则根据运算符优先级决定是否立即进行计算,或者将当前运算符压入opStack。 处理剩余运算符:遍历结束后,处理opStack中剩余的运算符。

代码详解

import java.util.Stack;

public class Main { public static int solution(String expression) { Stack numStack = new Stack<>(); Stack opStack = new Stack<>();

    int i = 0;
    while (i < expression.length()) {
        char ch = expression.charAt(i);
        
        if (Character.isDigit(ch)) {
            int num = 0;
            while (i < expression.length() && Character.isDigit(expression.charAt(i))) {
                num = num * 10 + (expression.charAt(i) - '0');
                i++;
            }
            numStack.push(num);
        } else if (ch == '(') {
            opStack.push(ch);
            i++;
        } else if (ch == ')') {
            while (!opStack.isEmpty() && opStack.peek() != '(') {
                numStack.push(applyOp(opStack.pop(), numStack.pop(), numStack.pop()));
            }
            opStack.pop(); // 弹出左括号
            i++;
        } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
            while (!opStack.isEmpty() && hasPrecedence(ch, opStack.peek())) {
                numStack.push(applyOp(opStack.pop(), numStack.pop(), numStack.pop()));
            }
            opStack.push(ch);
            i++;
        }
    }
    
    while (!opStack.isEmpty()) {
        numStack.push(applyOp(opStack.pop(), numStack.pop(), numStack.pop()));
    }
    
    return numStack.pop();
}

public static boolean hasPrecedence(char op1, char op2) {
    if (op2 == '(' || op2 == ')') {
        return false;
    }
    if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-')) {
        return false;
    }
    return true;
}

public static int applyOp(char op, int b, int a) {
    switch (op) {
        case '+':
            return a + b;
        case '-':
            return a - b;
        case '*':
            return a * b;
        case '/':
            if (b == 0) {
                throw new UnsupportedOperationException("Cannot divide by zero");
            }
            return a / b; // 确保结果为整数
    }
    return 0;
}

public static void main(String[] args) {
    System.out.println(solution("1+1") == 2);
    System.out.println(solution("3+4*5/(3+2)") == 7);
    System.out.println(solution("4+2*5-2/1") == 12);
    System.out.println(solution("(1+(4+5+2)-3)+(6+8)") == 23);
}

}

知识总结

栈的应用:栈在处理表达式计算、括号匹配等问题中非常有用。通过栈,我们可以轻松地回溯和处理嵌套的表达式。 
运算符优先级:理解运算符优先级是编写表达式解析器的关键。通过栈和优先级判断,我们可以确保计算顺序正确。 
整数除法:在实际编程中,整数除法的结果可能与浮点数除法不同,需要注意结果的类型和精度。 

学习建议

理解数据结构:栈、队列、链表等数据结构是编程的基础,理解它们的特性和应用场景非常重要。 
多练习:通过刷题,尤其是涉及栈和表达式解析的题目,可以加深对数据结构和算法的理解。 
总结经验:每次刷题后,总结解题思路和遇到的问题,形成自己的知识库。 

学习计划

制定刷题计划:每天刷一定数量的题目,逐步提高难度。 利用错题:对于做错的题目,分析错误原因,总结经验,避免再次犯错。 结合AI工具:利用MarsCode AI的刷题功能,获取解题思路和代码提示,提高学习效率。