BM49 Expression Evaluation

describe

Please write an integer calculator that supports addition, subtraction, multiplication and parentheses.

Data range: 0\le |s| \le 1000≤∣s∣≤100, to ensure that the calculation result is always within the integer range

Requirements: Space Complexity: O(n)O(n), Time Complexity O(n)O(n)

Example 1

enter:

"1+2"

return value:

3

Example 2

enter:

"(2*(3-4))*5

return value:
-10

Example 3

enter:

"3+2*3*4-1"

return value:

26

answer:

(dual stack solution)

The first stack s1 stores the operands (stores the result of the calculation)

The second stack s2 stores the operator

step:

The first step: remove all the strings of spaces;

Step 2: Traverse the string, if the current character is '( ', push it directly into the stack;

If the current character is ')', pop the operator stack s2 all the time (if s2 is not empty, and the top of the stack of s2 is not '('), the popped operator and operand stack The number is calculated continuously, and the result of the calculation is pushed back into the operand stack

Until the top of the operator stack s2 is '(', the stack will stop popping, and finally the top element in s2 will be popped.

If the current character is a numeric character , turn all the numeric characters into integers ("123"----->>123) at one time, and then push them into the operand stack; pay attention to the position of the record loop, jump to the already processed position;

If the current character is an operator , then:

       First determine whether the previous character is also an operator,

       If yes, maybe the current operator is not an operator, but negative, positive ('-', '+')

                    We need to add a 0 to the operand stack as -1 ===>0-1

       If not, take the top p of the operator stack s2 and compare it with the current character ch

                   If the level of the top of the stack is greater than the current character level, the operator stack s2 will always be popped out of the stack (if s2 is not empty, and the top of the stack of s2 is not '('), the popped operator and operand stack The two numbers are calculated continuously, and the result of the calculation is pushed back into the operand stack;

                  Otherwise, push the current character into the s2 stack and stop popping the stack

The last step: After traversing all the strings

All the elements in s2 are popped out of the stack, and the popped operator and the two numbers of the operand stack are continuously calculated, and the calculation result is pushed back into the operand stack

Finally, the element stored in s1 is the calculation result of this calculation formula

code:

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回表达式的值
     * @param s string字符串 待计算的表达式
     * @return int整型
     */
    //计算逻辑,从s1取出两个操作数,从s2中取出操作符,然后根据运算符进行计算即可
    public void cal(Stack<Integer> s1,Stack<Character> s2){
        if(s1.empty()||s1.size()<2) return;  //操作栈为空或小于2个数
        if(s2.empty()) return;  //操作符为空
        //操作数栈,出两个数
        int a=s1.pop(); int b=s1.pop();
        //操作符栈,出一个操作符
        char op=s2.pop();
        int ans=0;  //初始化两个数的运算结果
        if(op=='+'){
            ans=a+b;  //加法
        }
        else if(op=='-'){
            ans=b-a;  //减法 栈是倒序输出,a-b,其实栈中先输出b再输出a
        }
        else if(op=='*'){
            ans=a*b; //乘法
        }
        else{
            if(b!=0){
                ans=b/a;  //除法
            }
            else{
                return ;
            }
        }
        s1.push(ans);  //将计算结果重新置于操作数栈中
    }
    public int back(String s){
        s=s.replaceAll(" ",""); //去掉所有的空格
        Stack<Integer> s1=new Stack<>();  //存储数字
        Stack<Character> s2=new Stack<>();  //存储字符
        HashMap<Character,Integer> map=new HashMap<>();
        map.put('+',1);
        map.put('-',1);
        map.put('*',2);
        map.put('/',2);
        for(int i=0;i<s.length();i++){
            char ch=s.charAt(i);
            if(ch=='('){
                s2.push(ch);
            }
            else if(ch==')'){
                //计算到最近一个左括号为止
                while(!s2.empty()){ //如果不为空
                    if(s2.peek()!='('){  //计算到最近一个左括号为止
                        // 操作数栈出两个数。操作栈出一个操作数,计算的结果重新置于操作数栈中
                        cal(s1,s2);
                    }
                    else{//遇到了左括号'('
                        s2.pop();
                        break;  //停止出栈
                    }
                 }
             }
            else{//操作数和操作符
                if((ch-'0')>=0&&(ch-'0')<=9){//操作数
                    int j=i;  //记录操作数字符的范围
                    int u=0; //使字符的数字变成整数
                    while(j<s.length()&&(((ch=s.charAt(j))-'0')>=0&&((ch=s.charAt(j))-'0')<=9)){ //一次性读取所有的操作数
                        u=u*10+(ch-'0');
                        j++;  //一次性读取所有的数字字符
                    }
                    s1.push(u); //将形成的整数进到操作数栈中
                    i=j-1; //跳过已经遍历的数字字符
                }
                else{ //操作符
                    //为防止操作符后又是+1,-1 ,将正数,负数误判为操作符
                    //所以提前增加一个0,直接将-1变成0-1运算
                    if(i>0&&(s.charAt(i-1)=='('||s.charAt(i-1)=='+'||s.charAt(i-1)=='-')){
                        s1.push(0);
                    }
                    //新操作符入栈前,先比较操作符栈栈顶的优先级
                    //如果操作符栈不为空,且操作符栈栈顶不为‘(’
                    //栈顶的操作符等级大于等于当前的操作符
                    while(!s2.empty()&&s2.peek()!='('){
                        char pre=s2.peek(); //取栈顶
                        if(map.get(pre)>=map.get(ch)){  //如果栈顶元素等级大于等于当前操作符等级
                            cal(s1,s2);  //操作符出栈,操作数出栈两个数
                        }
                        else{  //当前操作符等级大于栈顶操作符
                            break;
                        } 
                    }//while
                    s2.push(ch);// 如果当前操作符大于栈顶的操作符,则进栈    
                 } 
              }//else
          }//for
        //遍历完所有的字符串,然后将栈中的元素全部计算
        while(!s2.empty()){
            cal(s1,s2);  //计算的结果全部存储操作数栈中
        }
        //最后的栈顶就是所有计算的结果
        return s1.peek();
    }
    public int solve (String s) {
        // write code here
       int sum=back(s);
       return sum;
    }
}

Guess you like

Origin blog.csdn.net/hgnuxc_1993/article/details/124149455