基本计算器 II(LeetCode第227题)java实现

一、题目描述

实现一个基本的计算器来计算一个简单的字符串表达式的值。

字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格  。 整数除法仅保留整数部分。

示例 1:

输入: "3+2*2"
输出: 7
示例 2:

输入: " 3/2 "
输出: 1
示例 3:

输入: " 3+5 / 2 "
输出: 5
说明:

你可以假设所给定的表达式都是有效的。
请不要使用内置的库函数 eval。

二、解题思路

方法一: 先求后缀树,再计算结果,消耗时间空间太高,不理想。

思路:

将表达式(中缀)转化为后缀
将后缀计算出结果
具体规则为:
1.中缀转后缀:
- 数字直接输出到后缀表达式
- 栈为空时,遇到运算符,直接入栈
- 遇到运算符,弹出所有优先级大于或等于该运算符的栈顶元素,并将该运算符入栈
- 将栈中元素依次出栈

例如:表达式:3+2 * 2
遇到3,直接输出到后缀表达式中,栈中元素为空,结果为: 栈: 空; 后缀表达式:3
遇到符号“+”,入栈,结果为: 栈:+ ; 后缀表达式:3
遇到2,直接输出,结果为: 栈:+; 后缀表达式: 3 2
遇到乘号*,入栈,结果为: 栈: * + ;后缀表达式:3 2
遇到2,直接输出,结果为: 栈: * + ;后缀表达式:3 2 2
最后,将元素出栈:结果为:后缀表达式:3 2 2 * +

2.计算后缀:
- 遇到数字,入栈
- 遇到运算符,弹出栈顶两个元素,做运算,并将结果入栈
- 重复上述步骤,直到表达式最右端

例如上述得到的后缀表达式为 3 2 2 * +
3 2 2 都是数字,入栈,结果为:栈:2 2 3
遇到* 号, 2 2 出栈,并计算,2*2 = 4, 4入栈,结果为:栈:4 3 ,表达式还剩一个加号
遇到+ 号,栈顶两个元素出栈并运算,4 3 做加法,4+3 =7
后缀表达式空了,计算完毕,输出结果:7

 

方法二:和方法一思路不同,但也好理解,代码量少,性能较好,推荐该方法。

思路如下:

 先令sign为‘+’,取新符号前处理上一个符号。 eg. 3 * 5 + 2   即· + 3 * 5 + 2 取到 * 时,处理 + 3,然后令sign = * ;取到 + 时,处理 3 * 5,令sign = +;最后 i == s.length() - 1,处理 15 + 2;

三、java代码如下

方法一:

class Solution {
    
    public int calculate(String s) {
        return calRst(backTempExp(s));
    }

    //一、计算输入字符串的后缀表达式
    public static LinkedList<String> backTempExp(String exp){
        Stack<String> stkEles = new Stack<> ();
        LinkedList<String> tempBackExp = new LinkedList<String> ();
        for (int i = 0; i < exp.length(); i++){
            //1. 遇到了数字
            if(Character.isDigit(exp.charAt(i))){
                //要处理 多位数,向后遍历到非数字为止
                int k = i + 1;
                for (; k < exp.length() && Character.isDigit(exp.charAt(k)); k++){

                }
                tempBackExp.add(exp.substring(i, k));
                //将i更新一下,因为在for循环中还要执行 i++
                i = k - 1;
                continue;
            }
            //2. 遇到了乘除 运算
            if(exp.charAt(i) == '/' || exp.charAt(i) == '*'){
                //遇到 优先级大于等于 自己的 就 出栈,加入后缀中
                while (!stkEles.isEmpty() && (stkEles.lastElement().equals('/') || stkEles.lastElement().equals('*'))){
                    tempBackExp.add(stkEles.pop());
                }
                //将当前字符 入栈
                stkEles.push(String.valueOf(exp.charAt(i)));
                continue;
            }
            //3. 遇到了加减 运算
            if(exp.charAt(i) == '+' || exp.charAt(i) == '-'){
                //遇到 优先级大于等于 自己的 就 出栈,加入后缀中
                while (!stkEles.isEmpty() && !Character.isDigit(stkEles.lastElement().charAt(0))){
                    tempBackExp.add(stkEles.pop());
                }
                //将当前字符 入栈
                stkEles.push(String.valueOf(exp.charAt(i)));
                continue;
            }
        }
        //4. 最后弹出栈中所有元素,放入后缀表达式中
        while (!stkEles.isEmpty()){
            tempBackExp.add(stkEles.pop());
        }
        return tempBackExp;
    }

    //二、计算最终结果
    public static int calRst(LinkedList<String> tempBackExp){
        Stack<Integer> calStk = new Stack<Integer> ();
        for (String c : tempBackExp){
            //1. 遇到数字 入栈
            if (Character.isDigit(c.charAt(0))){
                calStk.push(Integer.valueOf(c));
                continue;
            }
            //2. 遇到 加减乘除 运算符, 出栈两个数字元素,进行运算后,将计算结果再入栈
            else {
                int firstNum = calStk.pop();
                int secondNum = calStk.pop();
                switch (c.toCharArray()[0]) {
                    //注意减法和除法时,注意出栈的顺序与原表达式是相反的
                    case '+':
                        calStk.push(secondNum + firstNum);
                        continue;
                    case '-':
                        calStk.push(secondNum - firstNum);
                        continue;
                    case '*':
                        calStk.push(secondNum * firstNum);
                        continue;
                    case '/':
                        calStk.push(secondNum / firstNum);
                        continue;
                }
            }
        }
        return calStk.pop();
    }

}

方法二:

class Solution {

      public int calculate(String s) {
        int res = 0, d = 0;
        char sign = '+';
        Stack<Integer> nums = new Stack<Integer> ();
        for (int i = 0; i < s.length(); i++) {
            //加减乘除和空格的ASCII码都小于'0'
            if (s.charAt(i) >= '0'){
                d = d * 10 + s.charAt(i) - '0';
            }
            if((s.charAt(i) < '0' && s.charAt(i)!=' ') || i == s.length() - 1){
                if (sign == '+') {
                    nums.push(d);
                } else if (sign == '-') {
                    nums.push(-d);
                } else if (sign == '*' || sign == '/'){
                    int temp = sign == '*' ? nums.pop() * d : nums.pop() / d;
                    nums.push(temp);
                }
                sign = s.charAt(i);
                d = 0;
            }
        }
        for(int t : nums){
            res += t;
        }
        return res;
    }

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值