首页 > 试题广场 >

小猿的算术表达式

[编程题]小猿的算术表达式
  • 热度指数:170 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
小猿想对一种前缀表达式求值,该表达式定义如下:

1、每个表达式的形式都是 ( operator arg1 arg2 ),即由左括号,运算符,运算数1,运算数2,右括号组成。

2、运算符包括三种,分别是'+', '-', '*'。

3、运算符一定接收两个运算数,运算数间必须通过空格分隔,运算数可以是另外一个表达式或者不带符号的非负整数(小于10000000)。

(- 0 1) 代表 0 - 1;
(+ 1 2) 代表 1 + 2;
(+ (* 2 3) 1) 也是一个合法的表达式,代表了 2 * 3 + 1

4、在不产生歧义的情况下,空格也可以省略或者冗余。例如,

(+ 0 1) 和 ( +0 1) ,( +   0 1   ) 都被认为是合法的输入,且有相同的意义,代表 0 + 1。


输入描述:

第一行包含一个正整数T(T <= 100)。接下来会有T行输入。每一行包含一个表达式。每行数据所包含的字符数,不超过20000。

输入中的表达式只可能有两种不同类型的错误:1.括号不匹配,如+ 1 2没有括号。2.运算符缺失,如(2 3) 没有运算符。



输出描述:
对于合法的表达式,其值为Result,请输出 (Result Mod 10000000 + 10000000) Mod 10000000的结果,对于不合法的表达式,请输出“invalid”。
示例1

输入

4
(- 0 1)
(+ 2 20)
+  1 2)
(  2 2)

输出

9999999
22
invalid
invalid
import java.util.*;

public class Main {

/*
    1.将带括号的表达式转为不带括号的后缀表达式
        ( 1)遇到左括号和运算符运算符入栈,
        (2)遇到右括号弹出运算符直到左括号,弹出的运算符放到表达式
        (3)遇到数字直接加入表达式
    2. 计算不带括号的后缀表达式
        (1)遇到数字入数字栈
        (2)遇到操作符从栈中弹出两个数字计算
*/
    static Map<Character,Integer> priorityMap= new HashMap<>();

    public static void main(String[] args){
        Scanner scanner= new Scanner(System.in);
        priorityMap.put('+',1);
        priorityMap.put('-',1);
        priorityMap.put('*',2);
        priorityMap.put('/',2);
        priorityMap.put('(',0);
        priorityMap.put(')',0);

    
        int index=0;
        int N= scanner.nextInt();
        //第一个输入是数字
        //第二个输入是带空格的字符串,要用nextLine()接收
        
        //注意nextLine会接收到数字之后的"\n",要额外使用一个scanner.nextLine()接收该空行
        //真烦死了,这个sb输入
        String emptyLine= scanner.nextLine();
        while(scanner.hasNext()){
            index++;
            String preFix= scanner.nextLine();
            //System.out.println(preFix);
            List<String> postFix= getPostFix(preFix);
            //null说明表达式不合法
            if(postFix==null){
                System.out.println("invalid");
            }else{
                long value= calculate(postFix);
                if(value==-1){
                    System.out.println("invalid");
                }else{
                    System.out.println(value%10000000);
                }
                
            }

            //System.out.println("-----");
        }

    }
    


    public static long  calculate(List<String> postFix){
        Stack<Long> numStack= new Stack<>();
        for(int i=0;i<postFix.size();i++){
            String curStr= postFix.get(i);
            if(checkOpt(curStr)){
                long numAfter= numStack.pop()%10000000;;
                long numBefore= numStack.pop()%10000000;
                if(curStr.equals("+")){
                    numStack.push((numBefore+numAfter)%10000000);
                }
                if(curStr.equals("-")){
                    numStack.push((numBefore-numAfter)%10000000);
                }
                if(curStr.equals("*")){
                    numStack.push((numBefore*numAfter)%10000000);
                }
                if(curStr.equals("/")){
                    numStack.push((numBefore/numAfter)%10000000);
                }
            }else{
                numStack.push(Long.parseLong(curStr));
            }
        }
        if(numStack.size()>1){
            return -1;
        }
        return numStack.pop()+10000000;
    }


    public static List<String> getPostFix(String preFix){
        Stack<Character> optStack= new Stack<>();
        //System.out.println(preFix);
        List<String> postFix= new ArrayList<>();
        for(int i=0;i<preFix.length();i++){
            char cur= preFix.charAt(i);
            if(cur=='('){
                optStack.push(cur);
            }else if(cur==' '){
                continue;
                //数字直接作为表达式
            }else if(Character.isDigit(cur)){
                int loc= i;
                while(loc<preFix.length()){
                    char curChar= preFix.charAt(loc);
                    if(!Character.isDigit(curChar)){
                        break;
                    }
                    loc++;
                }
                //数字
                String digits= preFix.substring(i,loc);
                i=loc-1;
                postFix.add(digits);

            }else if(cur==')'){
                //System.out.println("右括号)");
                while(!optStack.isEmpty() && optStack.peek()!='('){
                    postFix.add(String.valueOf(optStack.pop()));
                }
                if(optStack.isEmpty()){
                    return null;
                    //弹出左括号
                }else{
                    //System.out.println(optStack.peek());
                    optStack.pop();
                }
                //+-*/运算符
            }else if(checkOpt(String.valueOf(cur))){
                String curString=String.valueOf(cur);
                if(optStack.isEmpty() ){
                    optStack.push(cur);
                }else{
                    while(!optStack.isEmpty() && priorityMap.get(optStack.peek())>=priorityMap.get(cur)){
                        postFix.add(String.valueOf(optStack.pop()));
                    }
                    optStack.push(cur);
                }

            }
        }

        return postFix;
    }

    public static boolean checkOpt(String str){
        return (str.equals("+") || str.equals("-")
                ||str.equals("*")||str.equals("/"));
    }


}

表达式转为后缀 然后计算后缀表达式 这题的输入很sb
编辑于 2022-08-14 17:27:49 回复(0)