leetcode 227 基本计算器:表达式通用解题模板

使用双栈解决中缀表达式计算

问题 :给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。

  • s 一定是一个有效表达式
  • 表达式中的所有整数都是非负整数,且在范围 [0, 2^31^ - 1]
  • s 由整数和算符 (’+’, ‘-’, ‘*’, ‘/’) 组成,中间由一些空格隔开

实际上还是逆波兰思想,只不过逆波兰将中缀转后缀时没有直接计算,这里计算了。另外本模板由于题目现在没有考虑「负数运算」和「负数符号,即类型 15/-5 这种情况,需要注意。

对于「任何表达式」,我们都可以使用两个栈 numsops:

  • nums:存放所有数字
  • ops: 存放所有数字以外的操作

然后从前往后遍历,将每个字符分情况讨论

  • 数字:取出一个完整的数字,放入 nums

  • 运算符:放入ops ,放入前把栈内能算的可以算掉(只有「栈内运算符」比「当前运算符」高or同级别才运算),使用现有的 numsops 进行计算,直到没有操作或者遇到左括号,计算结果放到 nums

  • ( : 直接加入 ops 中,等待与之匹配的 )

  • ) : 使用现有的 nums 和 ops 进行计算,直到遇到左边最近的一个左括号为止,计算结果放到 nums

class Solution{
    //1.先用map维护一个优先级字典并写好一个具体计算函数calc()
    Map<Character,Integer> map=new HashMap<>(){{
        put('-',1); put('+',1);
        put('*',2);	put('/',2);
        put('^',3);
    }};
    
    //2.建立两个栈,开始扫描
    public int claculate(String s){
        // tip:将所有的空格去掉,并将 (- 替换为 (0-,(+ 替换为 (0+
        // 当然这里也可以不预处理,而是放到循环里面去做判断
        s = s.replaceAll(" ", "");
        s = s.replaceAll("\\(-", "(0-");
        s = s.replaceAll("\\(\\+", "(0+");
		
        char[]expression=s.toCharArray();
        int capacity =s.length;
        
        Deque<Integer>nums=new ArrayDeque<>();
        Deque<Character> ops=new ArrayDeque<>();
        //防止第一个数为负数,先往nums里添加0
        nums.addLast(0);
        
        for(int i=0;i<capacity;i++){
            char c=expression[i];
            if(c=='('){
                ops.addLast(c);
            }else if(c==')'){
                //碰到右括号,计算到最近一个左括号为止
                while(!ops.isEmpty()){
                    if(ops.peekLast()=='('){
                        ops.pollLast();
                        break;
                    }else{
                        calc(nums,ops);
                    }
                }
            }else{
            //如果是数字
                if(isNumber(c)){
                    int temp=0;
                    int cur=i;
                    //取出一个完整的数字
                    while(j<capacity && isNumber(expression[j])){
                        temp=temp*10+(expression[j++]-'0');           
                    }
                    nums.addLast(temp);
                    i=j-1;
                }else{
                //如果是运算符
            // 有一个新操作要入栈时,先把栈内可以算的都算了 
        // 只有满足「栈内运算符」比「当前运算符」优先级高/同等,才进行运算
                    while(!ops.isEmpty() && ops.peekLast!='('){
                        char prev=ops.peekLast();
                        if(map.get(prev)>=map.get(c)){
                            calc(nums,ops);
                        }else{
                            break;
                        }
                    }
                    ops.addLast(c);
                }
            }
        }
        //运算符栈可能不为空,算完它
        while(!ops.isEmpty()) calc(nums,ops);
        return nums.peekLast();
    }
    
    boolean isNumber(char c){
        return Character.isDigit(c);
    }
    
    //具体的数学计算规则函数
    void calc(Deque<Integer>nums,Deque<Character>ops){
        if(nums.isEmpty()||nums.size<2) return;
        if(ops.isEmpty()) return;
        int second=nums.pollLast(),first=nums.pollLast();
        char op =ops.pollLast();
        int ans=0;
        if (op == '+') ans = first + second;
        else if (op == '-') ans = first - second;
        else if (op == '*') ans = first * second;
        else if (op == '/')  ans = first / second;
        else if (op == '^') ans = (int)Math.pow(a, b);
    	nums.addLast(ans);

    }
    
    
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值