首页 > 试题广场 >

表达式求值

[编程题]表达式求值
  • 热度指数:135169 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

给定一个字符串描述的算术表达式,计算出结果值。

输入字符串长度不超过 100 ,合法的字符包括 +, -, *, /, (, )0-9

数据范围:运算过程中和最终结果均满足 ,即只进行整型运算,确保输入的表达式合法

输入描述:

输入算术表达式



输出描述:

计算出结果值

示例1

输入

400+5

输出

405
首先这个题的难易程度肯定不是简单题,至少是中等题。另外这道题就是考察了中缀表达式转后缀或前缀表达式的原理,中间有一些细节需要处理,比如负号和减号的区分,个位数和多位数如何截取。
以下是我的代码:(有些地方还可以优化,但是我懒得优化了,比如获取多位数可以通过截取的方式而不是拼接的方式。
如果有正规用例导致我的代码不能正确计算的请指出。)
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();
        Stack<Character> s1 = new Stack<>();
        Stack<String> s2 = new Stack<>();
        String number = "";
        // 遍历表达式的每个字符,将中缀转化成后缀表达式
        for (int i = 0; i < expression.length(); i++) {
            if (isOperator(expression.charAt(i), i, expression)) {
                while (!s1.isEmpty() && s1.peek() != '(' &&
                        priorityCompare(s1.peek(), expression.charAt(i)) >= 0) {
                    s2.add(String.valueOf(s1.pop()));
                }
                s1.add(expression.charAt(i));
            } else if (expression.charAt(i) == '(') {
                s1.add(expression.charAt(i));
            } else if (expression.charAt(i) == ')') {
                while (s1.peek() != '(') {
                    s2.add(String.valueOf(s1.pop()));
                }
                s1.pop();
            } else if (Character.isDigit(expression.charAt(i))
                       || (expression.charAt(i) == '-' && (i == 0 ||
                               isNegativeNumberStart(i, expression)))) {
                // 当前字符是数字或者负号时
                number = String.valueOf(expression.charAt(i));
                for (int j = i + 1; j < expression.length(); j++) {
                    if (!Character.isDigit(expression.charAt(j))) {
                        break;
                    }
                    number = number + String.valueOf(expression.charAt(j));
                    i++;
                }
                s2.add(number);
            }
        }
        while (!s1.isEmpty()) {
            s2.add(String.valueOf(s1.pop()));
        }
        // 此时s2里就是我们已经转化好的后缀表达式,但是由于要从栈尾开始遍历,但栈只能从栈顶开始遍历,
        // 所以这里再遍历s2换到新的栈s3,此时s3的栈顶就是s2的栈尾,正常遍历s3就可以了(当然也可以使用双端栈就不用这么麻烦了)
        Stack<String> s3 = new Stack<>();
        while (!s2.isEmpty()) {
            s3.add(s2.pop());
        }
        Stack<Integer> s4 = new Stack<>();
        while (!s3.isEmpty()) {
            // 如果当前元素长度大于1,则必定是数字,比如负数-1 或 多位数11
            // 如果当前元素长度是1且isDigit==true,必定是数字
            if (s3.peek().length() > 1 || (s3.peek().length() == 1 &&
                                           Character.isDigit(s3.peek().charAt(0)))) {

                s4.add(Integer.parseInt(s3.pop()));
            } else {
                // 如果遇到运算符,则弹出栈里前两位元素进行运算
                s4.add(calculate(s4.pop(), s4.pop(), s3.pop().charAt(0)));
            }
        }
        System.out.println(s4.peek());
    }
    // 比较运算符的优先级
    public static int priorityCompare(char before, char after) {
        if (before == '+' || before == '-') {
            if (after == '*' || after == '/') {
                return -1;
            }
        } else if (before == '*' || before == '/') {
            if (after == '+' || after == '-') {
                return 1;
            }
        }
        return 0;
    }
    // 判断当前字符是否为运算符
    public static boolean isOperator(char c, int index, String expr) {
        if (c == '+' || c == '*' || c == '/') {
            return true;
        }
        // 如果是-,且不是首位,且不是负号,则说明是减号
        if (c == '-' && (index > 0 && !isNegativeNumberStart(index, expr))) {
            return true;
        }
        return false;
    }

    /**
     * 判断当前-字符是否为负号
     * @param index 当前字符的下标
     * @param expr 表达式
     * @return
     */
    public static boolean isNegativeNumberStart(int index, String expr) {
        // 如果-在首位,那么必定是负号而不是减号
        if (index == 0) {
            return true;
        }
        // 既然不是首位,那么获取前一位的字符
        char prevChar = expr.charAt(index - 1);
        // 如果前一位是以下字符则说明是负号而不是减号
        // 比如:1+(-1)、1+-1、1--1、1*-1、1/-1 这些都是负号前一位字符的特征
        return prevChar == '(' || prevChar == '+' || prevChar == '-' ||
               prevChar == '*' || prevChar == '/';
    }
    // 计算
    public static int calculate(int first, int second, char operator) {
        int result = 0;
        switch (operator) {
            case '+':
                result = first + second;
                break;
            case '-':
                // 注意这里是后一位 减去 前一位
                result = second - first;
                break;
            case '*':
                result = first * second;
                break;
            case '/':
                // 注意这里是后一位 除以 前一位
                result = second / first;
                break;
        }
        return result;
    }
}


发表于 2024-10-26 20:34:44 回复(0)
import java.math.BigDecimal;
import java.util.Scanner;
import java.util.Stack;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static BigDecimal cal(BigDecimal r,BigDecimal l,char c){
        if(c=='+') return r.add(l);
        if(c=='-') return l.subtract(r);
        if(c=='*') return r.multiply(l);
        if(c=='/') return l.divide(r);
        else return null;
    }
    ///////////////////////////
    static BigDecimal cal(String s){
        Stack<Character> opt=new Stack<>();
        Stack<BigDecimal> nums=new Stack<>();
        if(s.charAt(0)=='+'||s.charAt(0)=='-') nums.push(new BigDecimal(0));
        for(int i=0;i<s.length();i++){
            char c=s.charAt(i);
            String ns="";
            if(Character.isDigit(c)){
                while(i<s.length()&&Character.isDigit(s.charAt(i))){//遇到数字则将数字的所有位都读入
                    ns+=s.charAt(i);
                    i++;
                }
                BigDecimal de=new BigDecimal(ns);
                nums.push(de);
                i--;
                continue;
            }//
            ///////////////////////////////////
            if(!opt.empty()){
                if(c=='+'||c=='-'){
                    while(!opt.empty()&&opt.peek()!='('){//一定要先对前面的进行求和,避免先进性后面的减法再进行前面的减法,影响结果
                        BigDecimal td;
                        td=cal(nums.pop(),nums.pop(),opt.pop());
                        nums.push(td);
                    }
                    opt.push(c);
                    continue;
                }///////////////////////
               
                if(c=='*'||c=='/'){
                    if(opt.peek()=='*'||opt.peek()=='/'){
                        BigDecimal td=cal(nums.pop(),nums.pop(),opt.pop());
                        nums.push(td);
                    }
                    opt.push(c);continue;
                }/////////////////////////
               
                if(c==')'){
                    while (opt.peek() !='('){
                        BigDecimal td=cal(nums.pop(),nums.pop(),opt.pop());
                        nums.push(td);
                    }
                    opt.pop();
                    continue;
                }///////////////////////
               
                if(c=='(') {opt.push(c);
                if(s.charAt(i+1)=='+'||s.charAt(i+1)=='-') nums.push(new BigDecimal(0));
                continue;}
            }
            else opt.push(c);
            /////////////////////////////////////////
            }
        while(!opt.empty()){
            BigDecimal fd=cal(nums.pop(),nums.pop(),opt.pop());
            nums.push(fd);
        }
        return nums.pop();
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        String s=in.nextLine();
        System.out.println(cal(s));
    }
}

发表于 2024-09-12 13:19:15 回复(0)
正常来说是考察栈,但我玩一次赖的,直接调用js引擎执行字符串代码
import java.util.Scanner;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNext()) { // 注意 while 处理多个 case
            String exp = in.next();
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
           
            try {
                System.out.println(engine.eval(exp));
            } catch (Exception e) {

            }
           
        }
    }
}
发表于 2024-07-14 22:55:15 回复(1)
我花了一天,才写出这玩意,而且之前弄过类似的

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

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    public static void solution(String inputStr) {
        List<String> inputList = analysisToList(inputStr);//分析字符串组装每个元素到List中
        List<String> suffixList = convertToSuffix(inputList);//对List求后缀表达式
        //System.out.println(suffixList);
        //使用中缀表达式计算
        int result = calResultBySuffix(suffixList);
        System.out.println(result);
    }

    private static int calResultBySuffix(List<String> suffixList) {
        Stack<String> calStack = new Stack<>();
        for(int i = 0; i < suffixList.size(); i ++) {
            String suffixItem = suffixList.get(i);
            if(isNumber(suffixItem)) {
                //如果是数值,那么直接入栈  
                calStack.push(suffixItem);
            } else {
                //如果是非数字,弹出2个栈傎,并用该算术表达式计算
                int calResult = calOper(calStack.pop(), calStack.pop(), suffixItem);
                //计算出的表达式入栈
                calStack.push(String.valueOf(calResult));
            }
        }
        if(!calStack.isEmpty()) {
            return Integer.valueOf(calStack.pop());
        }
        return -1;
    }

    private static int calOper(String b, String a, String suffixItem) {
        int result = -1;
        int aInt = Integer.parseInt(a);
        int bInt = Integer.parseInt(b);
        switch(suffixItem) {
            case "+": result = aInt + bInt; break;
            case "-": result = aInt - bInt; break;
            case "*": result = aInt * bInt; break;
            case "/": result = aInt / bInt; break;
        }
        return result;
    }

    public static boolean isNumber(String chkStr) {
        try {
            Integer.parseInt(chkStr);
            return true;
        } catch(Exception e) {}
        return false;
    }

    public static List<String> convertToSuffix(List<String> expressionList) {
        List<String> suffixList = new ArrayList<>();
        Stack<String> stack = new Stack<>();
        for(int i = 0 ; i < expressionList.size(); i ++) {
            String curExpressionItem = expressionList.get(i);
            if(isNumber(curExpressionItem)) {
                //如果元素是一个数值, 那直接放到suffixList里
                suffixList.add(curExpressionItem);
            } else {
                //如果元素是非数值
                if(stack.isEmpty() || stack.peek().contains("(") || chkPeriorty(stack.peek(), curExpressionItem)) {
                    //栈为空,入栈
                    //栈顶是左括号,入栈
                    //元素优先级高于栈顶元素,入栈
                    stack.push(curExpressionItem);
                } else if(curExpressionItem.contains(")")) {
                    //如果遇到右括号,则出队列,直到遇到左括号
                    String popExpressionItem = stack.pop();
                    while(!popExpressionItem.contains("(")) {
                        if(!popExpressionItem.contains("(") && !popExpressionItem.contains(")")) {
                            suffixList.add(popExpressionItem);
                        }
                        popExpressionItem = stack.pop();
                    }
                } else if(!chkPeriorty(stack.peek(), curExpressionItem)) {
                    //元素优先级低于或等于栈顶元素,
                    //弹出当前栈顶,放到suffixList里
                    String popExpressionItem = stack.pop();
                    suffixList.add(popExpressionItem);
                    //继续判断栈顶, 如果元素优先级低于或等于栈顶元素,继续弹出栈顶元素放入suffixList里
                    while(!stack.isEmpty() && !stack.peek().contains("(") &&!chkPeriorty(stack.peek(), curExpressionItem)) {
                        popExpressionItem = stack.pop();
                        suffixList.add(popExpressionItem);
                    }
                    if(stack.isEmpty() || stack.peek().contains("(") || chkPeriorty(stack.peek(), curExpressionItem)) {
                        //
                        stack.push(curExpressionItem);
                    }
                }
            }
        }
        while(!stack.isEmpty()) {
            suffixList.add(stack.pop());
        }
        return suffixList;
    }

    private static boolean chkPeriorty(String peekItem, String curExpressionItem) {
        int result =  periorty(curExpressionItem) - periorty(peekItem);
        return result > 0 ? true : false;
    }

    private static int periorty(String chkFlag) {
        int score = -1;
        switch(chkFlag) {
            case "(": score = 10; break;
            case "*": score = 9; break;
            case "/": score = 9; break;
            case "+": score = 6; break;
            case "-": score = 6; break;
        }
        return score;
    }

    public static List<String> analysisToList(String inputStr) {
        List<String> result = new ArrayList<>();
        StringBuilder digitSb = new StringBuilder();
        for(int i = 0; i < inputStr.length(); i ++) {
            char chkChar = inputStr.charAt(i);
            if(Character.isDigit(chkChar)) {
                //当前字符为数字
                digitSb.append(chkChar);
                if(i + 1 < inputStr.length() && Character.isDigit(inputStr.charAt(i + 1))) {
                    //如果下一个字符为数字
                    //那么继续解析
                    continue;
                } else {
                    //下一个字符为非数字,说明数字已获取结束
                    result.add(digitSb.toString());
                    digitSb = new StringBuilder();
                }
            } else {
                //非数字
                //判断-符号是否为负号,还是运算符
                if(chkChar == '-') {
                    if(i - 1 < 0) {
                        //-号前面没有字符,则为负号
                        digitSb.append("-");
                        continue;
                    } else if(inputStr.charAt(i - 1) == '(') {
                        //-号前面非数字,则为负号
                        digitSb.append("-");
                        continue;
                    }
                    //其他情况 - 为运算符减号
                }
                result.add(String.valueOf(chkChar));
            }
        }
        return result;
    }

    public static void main(String[] args) {
        //解法1:自己完成的
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String inputStr = in.nextLine();
            solution(inputStr);
        }

        //解法2:调用api实现
    }
}

发表于 2024-01-16 19:37:08 回复(1)
import java.io.*;
public class Main{
    public static void main(String[] args) throws Exception {
        InputStream in = System.in;
        System.out.println(new ExprDemo().expr(in));
    }
//  一个对象表示一个括号,正常没有乘除就直接向结果里面塞数字,遇到乘除 ,弄一个新的集合装乘除结果,再遇到加减或者结束两个集合结果合并。流水线思考
    public static class ExprDemo {
        public char lastsign1 = 0, lastsign2 = 0;
        public int temp1 = 0, temp2 = 0;
        private static final char tempchar = 0;

        public int expr(InputStream in) throws IOException {
            int result = 0;
            char c;
            a: while((c = (char)in.read()) != '\n') {
                switch (c) {
                    case ')': break a;
                    case '(': temp2 = new ExprDemo().expr(in); break;
                    case '+':
                    case '-':
                        jisuan1(tempchar);
                        result = jisuan2(c, result);
                        break;
                    case '*':
                    case '/':
                        jisuan1(c);
                        break;
                    default: temp2 = temp2 * 10 + c - '0'; break;
                }
            }
            jisuan1(tempchar);
            result = jisuan2(tempchar, result);
            return result;
        }

        private void jisuan1(char c) {
            switch (lastsign2) {
                case 0: temp1 = temp2; break;
                case '*': temp1 *= temp2; break;
                case '/': temp1 /= temp2; break;
                default: break;
            }
            temp2 = 0;
            lastsign2 = c;
        }

        private int jisuan2(char c, int result) {
            switch (lastsign1) {
                case 0: result = temp1; break;
                case '-': result -= temp1; break;
                case '+': result += temp1; break;
                default: break;
            }
            temp1 = 0;
            lastsign1 = c;
            return result;
        }
    }

}
发表于 2023-10-04 22:52:48 回复(0)
这题绝对不是简单!!!!!!!!!!!!!!!!
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        String st = in.nextLine();
        int length = st.length();
        char[] a = st.toCharArray();
        Stack<Integer> snumber = new Stack();
        Stack<Character> sfuhao = new Stack();
        Stack<Integer> snumber1 = new Stack();
        Stack<Character> sfuhao1 = new Stack();
        boolean fu = false;
        int jieguo = 0;
        for (int i = 0; i < length; i++) {
            if (!(st.contains("+") || st.contains("-") || st.contains("*") ||
                    st.contains("/") || st.contains("(") || st.contains(")"))) {
                snumber.push(Integer.parseInt(st));
                break;
            }
            // + ,* ,/ ,( 直接入栈,并判断入站的数是否为负数
            if (a[i] == ('+') || a[i] == ('*')
                    || a[i] == ('/') || a[i] == ('(')) {
                if (st.indexOf(a[i]) == 0) {

                } else {
                    if (fu) {
                        snumber.push(-Integer.parseInt(st.substring(0, st.indexOf(a[i]))));
                        fu = false;
                    } else {
                        snumber.push(Integer.parseInt(st.substring(0, st.indexOf(a[i]))));
                    }
                }
                sfuhao.push(a[i]);
                st = st.substring(st.indexOf(a[i]) + 1);
            }
            // - 需要判断是 - 号还是负数
            if (a[i] == '-') {
                if (i == 0 || a[i - 1] == '(') {
                    fu = true;
                    st = st.substring(st.indexOf(a[i]) + 1);
                } else if (a[i - 1] == ')') {
                    st = st.substring(st.indexOf(a[i]) + 1);
                    sfuhao.push(a[i]);
                } else if (st.substring(0, st.indexOf(a[i])).length() == 0) {
                    fu = true;
                    st = st.substring(st.indexOf(a[i]) + 1);
                } else {
                    if (fu) {
                        snumber.push(-Integer.parseInt(st.substring(0, st.indexOf(a[i]))));
                        fu = false;
                    } else {
                        snumber.push(Integer.parseInt(st.substring(0, st.indexOf(a[i]))));
                    }

                    st = st.substring(st.indexOf(a[i]) + 1);
                    sfuhao.push(a[i]);
                }
                // if (a[0] == '-') {

                //     System.out.println(st);

                //     System.out.println(snumber.toString());
                //     System.out.println(sfuhao.toString());
                //     System.out.println(snumber1.toString());
                //     System.out.println(sfuhao1.toString());
                // }

            }

            //见了)出栈 直到遇到(
            if (a[i] == (')')) {

                if (a[i - 1] != (')')) {
                    snumber.push(Integer.parseInt(st.substring(0, st.indexOf(a[i]))));
                }
                if (i != length - 1) {
                    st = st.substring(st.indexOf(a[i]) + 1);
                }
                // if (a[0] == '3' && a[3] == '0') {
                //     System.out.println(snumber.toString());
                //     System.out.println(sfuhao.toString());
                //     System.out.println(snumber1.toString());
                //     System.out.println(sfuhao1.toString());
                // }
                while (sfuhao.lastElement() != '(') {
                    char fuhao = sfuhao.pop();
                    if (fuhao == '*') {
                        snumber1.push(snumber.pop());
                        jieguo = snumber1.pop() * snumber.pop();
                        snumber.push(jieguo);

                    } else if (fuhao == '/') {
                        snumber1.push(snumber.pop());
                        jieguo = snumber.pop() / snumber1.pop();
                        snumber.push(jieguo);

                    } else if (fuhao == '+' || fuhao == '-') {
                        snumber1.push(snumber.pop());
                        sfuhao1.push(fuhao);

                    }
                    if (sfuhao.size() == 0 || sfuhao.lastElement() == '(') {
                        snumber1.push(snumber.pop());
                        // if (a[0] == '(' && a[3] == '4') {
                        //     System.out.println(snumber.toString());
                        //     System.out.println(sfuhao.toString());
                        // }
                    }
                }

                //将(出栈
                sfuhao.pop();
                //sfuhao1 里面只有+ 与-

                while (sfuhao1.size() != 0) {
                    jieguo = snumber1.pop();
                    char fuhao = sfuhao1.pop();
                    if (fuhao == '+') {
                        jieguo = jieguo + snumber1.pop();
                    } else if (fuhao == '-') {
                        jieguo = jieguo - snumber1.pop();
                    }
                    if (sfuhao1.size() > 0) {
                        snumber1.push(jieguo);
                    }
                }
                snumber.push(jieguo);
                // if (a[0] == '(' && a[3] == '4') {
                //     System.out.println(snumber.toString());
                //     System.out.println(sfuhao.toString());
                //     System.out.println(snumber1.toString());
                //     System.out.println(sfuhao1.toString());
                // }
            }

        }


        while (sfuhao.size() != 0) {

            char fuhao = sfuhao.pop();
            if (fuhao == '*') {
                snumber1.push(snumber.pop());
                jieguo = snumber1.pop() * snumber.pop();
                snumber.push(jieguo);

            } else if (fuhao == '/') {
                snumber1.push(snumber.pop());
                jieguo = snumber.pop() / snumber1.pop();
                snumber.push(jieguo);

            } else if (fuhao == '+' || fuhao == '-') {
                snumber1.push(snumber.pop());
                sfuhao1.push(fuhao);

            }
            if (sfuhao.size() == 0) {
                snumber1.push(snumber.pop());
            }
        }
        //System.out.println(snumber1.toString());
        //System.out.println(sfuhao1.toString());
        while (sfuhao1.size() != 0) {
            jieguo = snumber1.pop();
            char fuhao = sfuhao1.pop();
            //System.out.println(jieguo);
            if (fuhao == '+') {
                jieguo = jieguo + snumber1.pop();

            } else if (fuhao == '-') {
                jieguo = jieguo - snumber1.pop();
            }
            if (sfuhao1.size() > 0) {
                snumber1.push(jieguo);
            }
        }
        System.out.print(jieguo);

    }
}

发表于 2023-09-22 12:48:06 回复(0)
为啥还有-1*(-1-1)这种样例
发表于 2023-07-01 23:40:45 回复(0)
import java.util.*;
import javax.script.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) throws Exception {
        Scanner scan = new  Scanner(System.in);
        String input = scan.nextLine();
        ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");
        System.out.println(scriptEngine.eval(input));
    }
}

发表于 2023-06-02 16:43:41 回复(1)
这题真的简单吗,为什么归到简单里面?
发表于 2023-03-22 23:14:28 回复(1)
我摊牌了,这道简单题我没有思路,废物
发表于 2023-03-17 15:13:35 回复(0)

描述

给定一个字符串描述的算术表达式,计算出结果值。

输入字符串长度不超过 100 ,合法的字符包括 +, -, *, /, (, )” , 0-9” 

数据范围:运算过程中和最终结果均满足 val2311  ,即只进行整型运算,确保输入的表达式合法

输入描述:

输入算术表达式

输出描述:

计算出结果值

示例1

输入:
400+5
复制
输出:
405
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    /**
    无视左括号
    将操作数压入操作数栈
    将运算符压入运算符栈
    在遇到右括号的时候,从运算符栈中弹出一个运算符,再从操作数栈中弹出所需的操作数,
    并且将运算结果压入操作数栈中
    */
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Stack<Integer> s1 = new Stack<>(); //操作数栈
        Stack<Character> s2 = new Stack<>(); //运算符栈
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String str = in.nextLine();
            int len = str.length();
            String tem = "";
            for(int i=0; i<len; i++) {
                char ch = str.charAt(i);
                switch(ch) {
                    case '(':
                    case '[':
                    case '{':
                        break; //忽略
                    case '+':
                    case '-':
                    case '*':
                    case '/':
                        s2.push(ch);//操作符入栈
                        break;
                    case ')':
                    case ']':
                    case '}':
                        //计算,并将操作数重新入栈
                        //1.弹出操作符
                        //2.弹出操作数1
                        //3.弹出操作数2
                        //计算,并将结果重新放到操作数栈
                        char flag = s2.pop();
                        Integer num1 = s1.pop();
                        Integer num2 = s1.pop();
                        Integer sum = null;
                        switch(flag) {
                            case '+':
                                sum = num1 + num2;
                                s1.push(sum);
                                break;
                            case '-':
                                sum = num1 - num2;
                                s1.push(sum);
                                break;
                            case '*':
                                sum = num1 * num2;
                                s1.push(sum);
                                break;
                            case '/':
                                sum = num1 / num2;
                                s1.push(sum);
                                break;
                        }
                        break;
                    default:
                        tem += String.valueOf(ch);
                        if(!nextIsNotNum(str, i, len)) {
                            s1.push(Integer.parseInt(tem));
                            tem = "";
                        }
                        break;
                }
            }
            //统计并输出
            int res = 0;
            while(!s1.isEmpty()) {
                res += s1.pop();
            }
            System.out.println(res);
        }
    }
    public static boolean nextIsNotNum(String str, int n, int len) {
        int temp = -1;
        try {
            temp = Integer.parseInt(String.valueOf(str.charAt(n+1)));
        } catch(Exception e) {
            temp = -1;
        }
        return temp != -1;
    }
}



发表于 2023-02-23 18:01:48 回复(3)
import java.util.Scanner;
import java.util.Stack;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    private static final String delimiter = "#";

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            String expression = in.nextLine();
            String suffixExpression = infixToSuffix(preProcessExpression(expression));
            Integer res = calcSuffix(suffixExpression);
            System.out.println(res);
        }
    }

    /**
     * 预处理表达式
     * @param expression
     * @return
     */
    public static String preProcessExpression(String expression) {
        StringBuilder strBuilder = new StringBuilder();
        if (expression != null && expression.length() > 0) {
            if (expression.charAt(0) == Opt.SUB.key) {
                strBuilder.append('0');
            }
            for (int i = 0; i < expression.length(); i++) {
                if (i + 1 < expression.length() && expression.charAt(i) == Opt.LEFT.key && expression.charAt(i + 1) == Opt.SUB.key) {
                    strBuilder.append(expression.charAt(i));
                    strBuilder.append('0');
                    continue;
                }
                strBuilder.append(expression.charAt(i));
            }
        }
        return strBuilder.toString();
    }

    /**
     * 中缀表达式转换成后缀表达式
     * @param infix
     * @return
     */
    public static String infixToSuffix(String infix) {
        StringBuilder suffixBuilder = new StringBuilder();
        Stack<Character> optStack = new Stack<>();
        for (int i = 0; i < infix.length(); i++) {
            char c = infix.charAt(i);
            //如果是数字,直接输出
            if(isNum(c)) {
                suffixBuilder.append(c);
                int j = i;
                while (j+1<infix.length()&&isNum(infix.charAt(j+1))) {
                    suffixBuilder.append(infix.charAt(++j));
                }
                i = j;
                suffixBuilder.append(delimiter);
                //如果不是数字
                //-- 是运算符 若栈顶元素优先级大于等于当前运算符 将栈顶元素出栈(加入到后缀表达式中) 直至栈顶元素小于当前元素优先级
                //-- 是( 直接入栈
                //-- 是) 将操作符栈出栈至匹配到一个( 出栈元素加入到后缀表达式中 (直接丢弃(不加入后缀表达式)
            } else {
                if (c == Opt.LEFT.key) {
                    optStack.push(c);
                } else if (c == ')') {
                    while(!optStack.isEmpty()&&optStack.peek()!=Opt.LEFT.key) {
                        suffixBuilder.append(optStack.pop());
                        suffixBuilder.append(delimiter);
                    }
                    optStack.pop();
                } else {
                    Opt curOpt = Opt.getOptByKey(c);
                    while(!optStack.isEmpty()&&Opt.getOptByKey(optStack.peek()).sort>= curOpt.sort) {
                        suffixBuilder.append(optStack.pop());
                        suffixBuilder.append(delimiter);
                    }
                    optStack.push(c);
                }
            }
        }
        while (!optStack.isEmpty()) {
            suffixBuilder.append(optStack.pop());
            suffixBuilder.append(delimiter);
        }
        return suffixBuilder.toString();
    }

    /**
     * 计算后缀表达式的值
     * @param suffix
     * @return
     */
    public static Integer calcSuffix(String suffix) {
        String[] signArr = suffix.split(delimiter);
        Stack<Integer> numStack = new Stack<>();
        for (int i = 0; i < signArr.length; i++) {
            try {
                int num = Integer.parseInt(signArr[i]);
                numStack.push(num);
            } catch(Exception e) {
                Integer right = numStack.pop();
                Integer left = numStack.pop();
                Integer res = Opt.calc(signArr[i].charAt(0), left, right);
                numStack.push(res);
            }
        }
        return numStack.peek();
    }

    public static boolean isNum(char c) {
        int tmp = c - '0';
        return 0 <= tmp && tmp <= 9;
    }

    /**
     * 运算符枚举
     */
    enum Opt {

        ADD('+', 2),
        SUB('-', 2),
        MULTI('*', 3),
        DIVIDE('/', 3),
        LEFT('(', 0);

        Opt(char key, int sort) {
            this.sort = sort;
            this.key = key;
        }

        public static Opt getOptByKey(char key) {
            Opt[] values = values();
            for (int i = 0; i < values.length; i++) {
                if (values[i].key == key) {
                    return values[i];
                }
            }
            return null;
        }

        public static Integer calc(char c, int left, int right) {
            Opt optByKey = getOptByKey(c);
            int res = 0;
            switch (optByKey) {
                case SUB:
                    res = left - right;
                    break;
                case ADD:
                    res = left + right;
                    break;
                case MULTI:
                    res = left * right;
                    break;
                case DIVIDE:
                    res = left / right;
                    break;
                default:
                    break;
            }
            return res;
        }

        private char key;

        private int sort;
    }
}
发表于 2023-01-27 21:21:12 回复(0)
解题思路:
    1)中缀表达式转后缀表达式
    2)依据后缀表达式计算
    参考链接:
    https://www.cnblogs.com/lzyws739307453/p/12907662.html#tid-dxYffc 
    https://www.bilibili.com/video/BV1xp4y1r7rc/?spm_id_from=333.788.recommend_more_video.-1&vd_source=62437a29d0413d5696b2f8935524e862 
    https://www.bilibili.com/video/BV1iz4y1k7Ct/?spm_id_from=333.788.recommend_more_video.-1&vd_source=62437a29d0413d5696b2f8935524e862 
    代码实现(2022-11-8 通过率:11/11):
    针对表达式存在负数的情况,可以正常处理。解决思路是,检查负号‘-’是否为二元运算符,若不是,则将负号不入栈,而是拼接到单元运算数上。
package com.ihang.learn.java.huawei;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.Stack;

/**
 * @author yaohangyang
 * @date 2022/11/7
 */
public class HJ54 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) {
            // 注意 while 处理多个 case
            System.out.println(hj54(in.nextLine()));
        }
    }

    //中缀表达式转后缀表达式
    public static Deque<String> Mid2End(String str) {
        //用于存运算数
        StringBuilder number = new StringBuilder();
        //后缀表达式
        Deque<String> deque = new LinkedList<>();
        //运算操作符
        Stack<Character> stack = new Stack<>();
        boolean flag = false;
        for(int i = 0; i<str.length(); i++){
            char c = str.charAt(i);
            if(c>='0' && c<='9'){
                number.append(c);
            }else {
                if(number.length()>0){
                    if(flag){
                        deque.add("-"+number.toString());
                        flag = false;
                    }else {
                        deque.add(number.toString());
                    }
                    number.delete(0,number.length());
                }
               if(c=='('){
                   stack.push(c);
               }else if(c==')'){
                   char top = stack.peek();
                   while (top!='('){
                       deque.add(stack.pop()+"");
                       top = stack.peek();
                   }
                   stack.pop();
               }else if(c=='-' && (i==0 || str.charAt(i-1)=='(')){
                   // 用于处理运算数是负数的情况 比如:-1*(-1-1) => -1 -1 1 - *
                   flag = true;
               }else  {
                   if(stack.size()<=0 || stack.peek()=='(' || opeCompare(c,stack.peek())){
                       stack.push(c);
                   }else {
                       while (stack.size()>0 && stack.peek()!='(' && !opeCompare(c,stack.peek())){
                           deque.add(stack.pop()+"");
                       }
                       stack.push(c);
                   }
               }
            }
        }
        if(number.length()>0){
            deque.add(number.toString());
        }
        while (stack.size()>0){
            deque.add(stack.pop()+"");
        }

        return deque;
    }

    //运算符优先级比较
    public static  boolean opeCompare(char a ,char b){
        if(a=='*' || a=='/'){
            if(b=='+' || b=='-'){
                return true;
            }
        }
        return false;
    }

    //后缀表达式计算
    public static int hj54(String str){
        Deque<String> deque = Mid2End(str);
        Stack<Integer> stack = new Stack<>();
        while (deque.size()>0){
            String s = deque.pollFirst();
            if(s.charAt(s.length()-1)>='0' && s.charAt(s.length()-1)<='9'){
                stack.push(Integer.parseInt(s));
            }else {
                int b = stack.pop();
                int a = stack.pop();
                int r = 0;
                switch (s.charAt(0)){
                    case '*':
                        r = a*b;
                        break;
                    case '/':
                        r = a/b;
                        break;
                    case '+':
                        r = a+b;
                        break;
                    case '-':
                        r = a-b;
                        break;
                    default:
                        break;
                }
                stack.push(r);
            }
        }
        return stack.pop();
    }
}


发表于 2022-11-08 00:28:25 回复(1)
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.util.Stack;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = br.readLine();
        System.out.println(calculate(line));
    }
    public static int calculate(String line){
        Stack<Integer> stack = new Stack<>();
        char sign = '+';
        int number = 0;
        int len = line.length();
        char[] chars = line.toCharArray();
        for(int i = 0; i < len; i++){
            char ch = chars[i];
            if(ch == ' ')continue;
            if(Character.isDigit(ch)){
                number = number * 10 + ch - '0';
            }
            if(ch == '('){
                int count = 1;
                int j = i + 1;
                while(count > 0){
                    if(chars[j] == ')')count--;
                    if(chars[j] == '(')count++;
                    j++;
                }
                //递归,解小括号中的表达式
                number = calculate(line.substring(i + 1, j - 1));
                i = j - 1;
            }
            if(!Character.isDigit(ch) || i == len - 1){
                if(sign == '+'){
                    stack.push(number);
                }else if(sign == '-'){
                    stack.push(-1 *number);
                }else if(sign =='*'){
                    stack.push(stack.pop() * number);
                }else if(sign == '/'){
                    stack.push(stack.pop() / number);
                }
                //更新符号
                sign = ch;
                //刷新数字
                number = 0;
            }
        }
        //栈中数字求和得到结果
        int ans = 0;
        while (!stack.isEmpty()) {
            ans += stack.pop();
        }
        return ans;
    }
}

发表于 2022-08-21 12:07:33 回复(0)
题解思路:感觉处理这种题一定要先弄明白算术运算的逻辑,包括对负数和括号的处理。如果了解中缀表达式如何转后缀表达式,那处理这个问题的思路就很清晰了。难点是对于负数的处理。我的解决方法是:定义两个栈,分别用于保存数值和运算符。保存数值时需要对负数进行判断。保存运算符时,只有当运算符栈的栈顶为* 或 / 的时候再出栈处理,先处理乘除再处理加减。遇到左括号时,直接入栈即可,只有当遇到右括号再出栈处理。写的很仓促,也没有再优化,哪里不对的地方希望朋友们指正!

import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
import java.util.Stack;
public class Main {
    public static void main(String[] args) throws IOException {
        InputStream in = System.in;
        Scanner scanner = new Scanner(in);
        String str = scanner.nextLine();
        int result = getEvaluation(str);
        System.out.println(result);
    }
       private static int getEvaluation(String str) {
        if (str == null || str.length() == 0) return 0;
        // 记录数值
        Stack<Integer> arithmetic = new Stack<>();
        // 记录运算符
        Stack<Character> operator = new Stack<>();
        int i = 0;
        while(i < str.length()) {
            // 对负数的判断
            boolean negative = false;
            if ((str.charAt(i) == '-' && arithmetic.isEmpty()) ||
                    (str.charAt(i) == '-' && !(str.charAt(i-1) >= '0' && str.charAt(i-1) <= '9') && str.charAt(i-1) != ')')) {
                negative = true;
                i++;
            }
            // 保存数值
            if (i < str.length() && str.charAt(i)  >= '0' && str.charAt(i) <= '9'){
                StringBuilder builder = new StringBuilder();
                while (i < str.length() && str.charAt(i)  >= '0' && str.charAt(i) <= '9'){
                    builder.append(str.charAt(i));
                    i++;
                }
                arithmetic.push(negative ? -Integer.valueOf(builder.toString()) : Integer.valueOf(builder.toString()));
            }
            // 出栈处理数值
            if (i < str.length() && (str.charAt(i) == '+' || str.charAt(i) == '-')) {
                while (!operator.isEmpty() && (operator.peek() == '*' || operator.peek() == '/')) {
                    Character op = operator.pop();
                    Integer n1 = arithmetic.pop();
                    Integer n2 = arithmetic.pop();
                    arithmetic.push(operation(n2, n1, op));
                }
                while (!operator.isEmpty() && (operator.peek() == '+' || operator.peek() == '-')){
                        Character op = operator.pop();
                        Integer n1 = arithmetic.pop();
                        Integer n2 = arithmetic.pop();
                        arithmetic.push(operation(n2, n1, op));
                    }
                operator.push(str.charAt(i));
                i++;
            }
            // 遇到右括号再出栈处理
            else if (i < str.length() && (str.charAt(i) == ')')){
               while (true){
                   Character op = operator.pop();
                   if (op == '(') break;
                   Integer n1 = arithmetic.pop();
                   Integer n2 = arithmetic.pop();
                   arithmetic.push(operation(n2,n1,op));
               }
               i++;
            }
            // 其他情况运算符入栈即可
            else{
                if (i == str.length())
                    break;
                operator.push(str.charAt(i));
                i++;
            }
        }
        while (!operator.isEmpty()){
            Character op = operator.pop();
            Integer n1 = arithmetic.pop();
            Integer n2 = arithmetic.pop();
            arithmetic.push(operation(n2,n1,op));
        }
        return arithmetic.pop();
    }

    /**
     * 基础运算
     */
    private static Integer operation(Integer n1, Integer n2, Character op) {
        if (op == '+')
            return n1 + n2;
        else if (op == '-')
            return n1 - n2;
        else if (op == '*')
            return n1 * n2;
        else
            return n1 / n2;
    }
}


发表于 2022-08-03 18:34:54 回复(0)

问题信息

难度:
46条回答 42845浏览

热门推荐

通过挑战的用户

表达式求值