算法通关村 —— 计算器问题解析

算法通关村 —— 计算器问题解析

栈有很多经典的问题,前面我们已经学习了像括号匹配这样经典的问题,除此之外,表达式计算和计算器问题天然的适合使用栈来解决,不过,解决起来可能略复杂一些。

计算器问题详细如下: 给定一个字符串表达式s,请你实现一个基本计算器来计算并返回它的值。整数出发仅保留整数部分。 其中假设表达式总是有效的,所有中间结果在[-231. 231-1]的范围内。注意!不允许使用任何将字符串作为数学表达式的内置函数,比如eval();

输入:s = "3+3*3"
输出:12

解决该问题最好的工具就是栈。在计算中先算乘除再算加减,所以我们先进行乘除运算,然后将运算后的整数值返回原表达式的相应位置。此后整个表达式就变成一系列整数加减后的值了。

所以,我们可以先用一个栈来保存乘除运算后的整数值。然后,将加减号后的数字直接压入栈中。最后,对乘除号后的数字,可以直接与栈顶元素计算,并替换栈顶元素为计算后的结果。

总的来说便是去遍历指定的字符串s,并用变量preSign来记录每个数字前的运算符,第一个数字之前的运算符视为加号。每次遍历到数字末尾,则根据preSign来决定计算方式,情况如下:

加号:将数字入栈;  减号:将数字的相反数入栈; 

乘除号:计算数字与栈顶元素,并将栈顶元素替换为计算结果

若读到一个运算符,或者遍历到字符串末尾,即认为是遍历到数字末尾,因为我们先计算了乘除,再压加减号的数字入栈,所以后面若遍历到符号则证明已经遍历完。处理完该数字后,更新preSign为当前遍历的字符。

遍历完字符串s后,将栈中元素累加则可得到字符串表达式的值。

具体实现代码如下:

class Solution {
    public int calculate(String s) {
        // 构造存放计算结果的栈
        Deque<Integer> stack = new ArrayDeque<Integer>();
        // preSign:标志符号的变量,第一个为加号 num: 存储数字及计算结果入栈
        char preSign = '+';
        int num = 0, n = s.length(); 
        // 遍历字符串
        for(int i = 0; i < n; i++){
            // 判断是否为数字
            if(Character.isDigit(s.charAt(i))){
                // 先入栈的数字为大位的数,所以后面如果又入了数字,则需要前面的数字乘10再相加
                num = num*10 + s.charAt(i) - '0';
            }
            // 若遍历到运算符或者遍历到末尾了
            if (!Character.isDigit(s.charAt(i)) && s.charAt(i) != ' ' || i == n - 1) {
                switch(preSign){  // 通过switch分情况判断符号执行
                    case '+': // 加号则直接入栈等待计算
                        stack.push(num);
                        break;
                    case '-': // 符号将相反数入栈
                        stack.push(-num);
                        break;
                    case '*': // 乘号则将栈顶元素出栈进行乘法运算后把结果入栈
                        stack.push(stack.pop() * num);
                        break;
                    default: // 除法同理
                        stack.push(stack.pop() / num);
                }
                preSign = s.charAt(i); // 运算符号更新
                num = 0; // 计算结果归零
            }
        }
        int ans = 0; // 存储答案值
        while(!stack.isEmpty()){
            ans += stack.pop(); // 将栈中所有元素出栈相加
        }
        return ans;        
    }

    // 测试类
    public static void main(String[] args) {
        System.out.println(calculate( "3+2*2"));
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值