BM49 表达式求值

1.题目描述

请写一个整数计算器,支持加减乘三种运算和括号。

数据范围:0≤∣s∣≤1000≤∣s∣≤100,保证计算结果始终在整型范围内

要求:空间复杂度: O(n)O(n),时间复杂度 O(n)O(n)

示例1

输入:

"1+2"

返回值:

3

示例2

输入:

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

返回值:

-10

示例3

输入:

"3+2*3*4-1"

返回值:

26

2.解题思路

使用两个栈,其中操作数栈nums用于循环的保存每一个连续的数值,运算符栈opts用于保存遍历到的运算符。需要注意的是,如果当前遍历到的运算符的算数优先级<=栈顶运算符的优先级,则现将栈顶运算符和两个操作数出栈运算,并把中间结果再次入栈到nums中以备后用。

其中根据当前遍历到的字符c不同,主要分为以下几种情况:

1.c为左括号,直接入操作数栈;

2.c为数字,如果下一个仍为数字,通过num = num * 10  + (c - '0')的方式计算出这个数字的值,并把结果加入到nums中,注:退出循环后要把i-=1,因为外层while循环会有一个i+=1的操作,如果不前移一位,会出现部分字符的漏检;

3.c为右括号,循环弹出运算符栈中的栈顶操作符,进行运算,直到遇到与该括号相匹配的第一个左括号为止;

4.c为运算符,有一种特殊情况,就是1+(-2)时,如果遇到c = '-',且判断它前一个位置为(,那么要在操作数栈中push一个0进去,方便负号的处理;对于其他情况,我们就需要循环的判断运算符栈顶元素的优先级是否大于等于当前运算符,如果是,优先将栈顶的运算符进行计算,最后再把当前运算符压入栈中

通过以上操作,最终操作数栈中保存的即为最终的结果,返回nums.pop()即为所求

3.代码实现

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回表达式的值
     * @param s string字符串 待计算的表达式
     * @return int整型
     */
    public int solve (String s) {
        //定义一个hashMap保存运算符的优先级
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        map.put('+', 1);
        map.put('-', 1);
        map.put('*', 2);
        //使用两个栈:运算符栈和操作数栈
        Stack<Character> opts = new Stack<>();
        Stack<Integer> nums = new Stack<>();
        //防止读取到负号时,栈中只有一个操作数
        nums.push(0);
        char[] charArray = s.toCharArray();
        int i = 0;
        while (i < charArray.length) {
            char c = charArray[i];
            //左括号直接入运算符栈
            if (c == '(') {
                opts.push(c);
            } else if (c == ')') { //右括号直到弹出匹配的左括号才结束
                while (opts.peek() != '(') {
                    calculate(opts, nums);
                }
                opts.pop();
            } else if (Character.isDigit(
                           c)) { //计算出连续数字对应的整数并入操作数栈
                int num = 0;
                while (i < charArray.length && Character.isDigit(charArray[i])) {
                    num = num * 10 + (charArray[i] - '0');
                    i += 1;
                }
                i -= 1;
                nums.push(num);
            } else { //运算符需要根据优先级决定计算方式
                //如果当前操作符前是'(',表示当前操作符为‘-’,需要特殊处理
                if (i > 0 && charArray[i - 1] == '(') {
                    nums.push(0);
                }
                int priority = map.get(c);
                while (!opts.isEmpty() && opts.peek() != '(' &&
                        priority <= map.get(opts.peek())) {
                    calculate(opts, nums);
                }
                opts.push(c);
            }
            i += 1;
        }
        while (!opts.isEmpty()) {
            calculate(opts, nums);
        }
        return nums.pop();
    }

    public void calculate(Stack<Character> opts, Stack<Integer> nums) {
        if (opts.size() < 1 || nums.size() < 2) return;
        char operator = opts.pop();
        int m = nums.pop();
        int n = nums.pop();
        int res = 0;
        if (operator == '+') {
            res = n + m;
        } else if (operator == '-') {
            res = n - m;
        } else {
            res = n * m;
        }
        nums.push(res);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值