首页 > 试题广场 >

表达式求值

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

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

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

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

输入描述:

输入算术表达式



输出描述:

计算出结果值

示例1

输入

400+5

输出

405
我花了一天,才写出这玩意,而且之前弄过类似的

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 回复(2)
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)
先写出不考虑括号的情况,最后遇到括号时调用没有括号的程序
import java.util.*;
public class Main {
    static int index = 0;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String input = sc.next();
        int res = calculate(input);
        System.out.println(res);
    }
    public static int calculate(String s) {
        Deque<Integer> stack = new LinkedList<>();
        int length = s.length();
        char prevSign = '+';
        while (index < length) {
            char c = s.charAt(index);
            if (c == '(') {
                index++;
                int num = calculate(s); // 遇到左括号时,递归调用获取括号内表达式的值
                calculateCurData(stack, prevSign, num); // 根据括号前面的一个运算符处理括号内表达式的计算结果
                if (index < length) prevSign = s.charAt(index++); // 求出右括号后面紧跟的符号
            } else if (prevSign == ')') {
                break;
            } else { // 求不包含括号时的表达式的值
                int num = 0;
                while (index < length && Character.isDigit(s.charAt(index))) {
                    num = num * 10 + s.charAt(index) - '0';
                    index++;
                }
                calculateCurData(stack, prevSign, num);
                if (index == length) break;
                prevSign = s.charAt(index++);
            }
        }
        return calculateRes(stack);
    }

    private static void calculateCurData(Deque<Integer> stack, char prevSign, int num) {
        if (prevSign == '+') {
            stack.push(num);
        }
        else if (prevSign == '-') {
            stack.push(-num);
        }
        else if (prevSign == '*') {
            stack.push(stack.pop() * num);
        }
        else if (prevSign == '/') {
            stack.push(stack.pop() / num);
        }
    }

     private static int calculateRes(Deque<Integer> stack) {
        int res = 0;
        while (!stack.isEmpty()) {
            res += stack.pop();
        }
        return res;
    }
}




发表于 2022-07-04 16:39:31 回复(1)
import java.util.HashMap;
import java.util.Scanner;
import java.util.Stack;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        char[] charArray = (sc.next() + "#").toCharArray();
        Stack<Character> signStack = new Stack<>();
        Stack<Integer> numStack = new Stack<>();
        HashMap<Character, Integer> map = new HashMap<>();
        map.put('+', 0);
        map.put('-', 1);
        map.put('*', 2);
        map.put('/', 3);
        map.put('(', 4);
        map.put(')', 5);
        map.put('#', 6);
        char[][] chars = new char[][]{
                {'>', '>', '<', '<', '<', '>', '>'},
                {'>', '>', '<', '<', '<', '>', '>'},
                {'>', '>', '>', '>', '<', '>', '>'},
                {'>', '>', '>', '>', '<', '>', '>'},
                {'<', '<', '<', '<', '<', '=', 'e'},
                {'e', 'e', 'e', 'e', 'e', 'e', 'e'},
                {'<', '<', '<', '<', '<', 'e', '='},
        };
        signStack.push('#');
        int i = 0;
        while (i < charArray.length) {
            int sign = 1;
            if ((i == 0 || charArray[i - 1] == '(') && charArray[i] == '-') {
                i++;
                sign = -1;
            }
            if (isNum(charArray[i])) {
                int sum = 0;
                while (isNum(charArray[i])) {
                    sum *= 10;
                    sum += charArray[i] - '0';
                    i++;
                }
                numStack.push(sign * sum);
            } else {
                switch (chars[map.get(signStack.peek())][map.get(charArray[i])]) {
                    case '<':
                        signStack.push(charArray[i++]);
                        break;
                    case '>':
                        Integer rightVal = numStack.pop();
                        Integer leftVal = numStack.pop();
                        Character ops = signStack.pop();
                        numStack.push(operate(leftVal, rightVal, ops));
                        break;
                    case '=':
                        signStack.pop();
                        i++;
                        break;
                    default:
                        throw new RuntimeException("error");
                }
            }
        }
        if (signStack.isEmpty() && numStack.size() == 1) System.out.println(numStack.peek());
    }

    private static Integer operate(Integer leftVal, Integer rightVal, Character ops) {
        switch (ops) {
            case '+':
                return leftVal + rightVal;
            case '-':
                return leftVal - rightVal;
            case '*':
                return leftVal * rightVal;
            case '/':
                return leftVal / rightVal;
            default:
                return null;
        }
    }

    private static boolean isNum(char c) {
        return c >= '0' && c <= '9';
    }
}

发表于 2022-06-23 23:31:37 回复(0)
这是道简单题?我是沙笔,不想刷NM算法题了,好想上岸
发表于 2022-06-22 23:23:34 回复(7)
// 提交一个笨方法
public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    String str = in.nextLine();
    while (str.contains(")")) {
        int start = 0;
        // 发现反括号往前搜索最近的一个括号,先解析本组数据
        int end = str.indexOf(")");
        for (int i = end; i >= 0; i--) {
            if ('(' == str.charAt(i)) {
                start = i;
                break;
            }
        }
        String tmp = str.substring(start, end + 1);
        // System.out.println("获取括号 tmp=" + tmp);
        int n = getResult(str.substring(start + 1, end));
        str = str.replace(tmp, String.valueOf(n));
    }
    System.out.println(getResult(str) + "");
}

private static int getResult(String str) {
    // 运算乘法
    while (str.contains("*")) {
        int pre = getPreNum(str, "*", "\\d+");
        int next = getNextNum(str, "*");
        str = str.replace(pre+"*"+next, String.valueOf(pre*next));
        // System.out.println("运算* str=" + str);
    }
    // 运算除法
    while (str.contains("/")) {
        int pre = getPreNum(str, "*/", "\\d+");
        int next = getNextNum(str, "/");
        str = str.replace(pre+"/"+next, String.valueOf(pre/next));
        // System.out.println("运算/ str=" + str);
    }

    str = str.replace("+-", "-");
    str = str.replace("--", "+");
    if (str.startsWith("+")) {
        str = str.substring(1);
    }
    // 运算加法
    while (str.contains("+")) {
        str = str.replaceAll("\\+0|\\-0", "");
        int pre = getPreNum(str, "+", "\\-*\\d+"); // 加减法运算符前面的数把符号也算上
        int next = getNextNum(str, "+");
        // System.out.println("运算+ pre=" + pre + ",next=" + next);
        str = str.replace(pre+"+"+next, pre < 0? "+" + String.valueOf(pre+next) : String.valueOf(pre+next));
    }

    str = str.replace("+-", "-");
    str = str.replace("--", "+");
    if (str.startsWith("+")) {
        str = str.substring(1);
    }
    // 运算减法
    while (str.substring(1).contains("-")) {
        str = str.replaceAll("\\+0|\\-0", "");
        if (str.startsWith("-")) {
            str = str.substring(1);
            int pre = getPreNum(str, "-", "\\-*\\d+"); // 加减法运算符前面的数把符号也算上
            int next = getNextNum(str, "-");
            str = "-" + str.replace(pre+"-"+next, String.valueOf(pre+next));
        } else {
            int pre = getPreNum(str, "-", "\\-*\\d+"); // 加减法运算符前面的数把符号也算上
            int next = getNextNum(str, "-");
            str = str.replace(pre+"-"+next, String.valueOf(pre-next));
        }
        // System.out.println("运算- str=" + str);
    }
    return str.startsWith("-") ? -Integer.parseInt(str.substring(1)) : Integer.parseInt(str);
}

// 获取运算符前面的数
private static int getPreNum(String str, String fuhao, String relgex) {
    int n = str.indexOf(fuhao);
    String result = "";
    String tmp = result;
    while (true && n > 0) {
        tmp = String.valueOf(str.charAt((n - 1))) + tmp;
        if (!tmp.matches(relgex)) {
            break;
        }
        result = tmp;
        // System.out.println("前面数=" + tmp);
        --n;
    }
    return result == ""? 0: (result.contains("-")? -Integer.parseInt(result.substring(1)): Integer.parseInt(result));
}

// 获取运算符后面的数
private static int getNextNum(String str, String fuhao) {
    int n = str.indexOf(fuhao);
    String result = "";
    String tmp = result;
    while (true && n < str.length() - 1) {
        tmp = tmp + String.valueOf(str.charAt((n + 1)));
        if (!tmp.matches("\\-|\\-*\\d+")) {
            break;
        }
        result = tmp;
        // System.out.println("后面数=" + tmp);
        ++n;
    }
    return result == "" ? 0: (result.startsWith("-") ? -Integer.parseInt(result.substring(1)): Integer.parseInt(result));
}
发表于 2022-06-19 21:47:04 回复(0)

问题信息

难度:
41条回答 38807浏览

热门推荐

通过挑战的用户

查看代码