leetcode150. 逆波兰表达式求值&leetcode227基本计算器 II

leetcode150逆波兰表达式传送门

题目:根据逆波兰表示法,求表达式的值。有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。说明: 1.整数除法只保留整数部分。2.表达式总会得出有效数值且不存在除数为 0 的情况。

输入: ["2", "1", "+", "3", "*"]     
输出: 9          解释: ((2 + 1) * 3) = 9

输入: ["4", "13", "5", "/", "+"]    
输出: 6          解释: (4 + (13 / 5)) = 6
  1. 遇到数字, 把数字入栈
  2. 否则 遇到运算符, 栈中弹出来两个数 (第二个数是在运算符前) 根据运算符进行运算, 得到的结果重新入栈
这里主要是根据不同运算符,对栈顶操作比较巧妙
	public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for (String s : tokens) {
            if (s.equals("+")) {
                stack.push(stack.pop() + stack.pop());
            } else if (s.equals("-")) {
                stack.push(-stack.pop() + stack.pop()); // 栈顶是减数,取反
            } else if (s.equals("*")) {
                stack.push(stack.pop() * stack.pop());
            } else if (s.equals("/")) { 
                int num = stack.pop();  // 先临时保存栈顶(除数)
                stack.push(stack.pop() / num);
            } else {  //数字, 注意负数如-11这种情况,所以不能用s[0]>=’0’&&s[0]<=’9’判断数字
                stack.push(Integer.parseInt(s));
            }
        }
        return stack.pop();
    }

leetcode227. 基本计算器II 传送门

题目:   实现一个基本的计算器来计算一个简单的字符串表达式的值。
可以假设所给定的表达式都是有效的。
字符串表达式仅包含非负整数,+-*/ 四种运算符和空格。
 整数除法仅保留整数部分。
输入: " 3+5 / 2 "           
输出: 5

方法1. 传统数字栈+符号栈

一定要注意过滤空格!
 	public int calculate(String s) {
        Stack<Integer> stack = new Stack<Integer>(); // 数字栈
        Stack<Character> chStack = new Stack<Character>();//运算符栈
        int sum = 0; // 多个字符拼接成一个数字
        for (int i = 0; i < s.length(); ++i) {
            char ch = s.charAt(i);
            if (ch <= '9' && ch >= '0') { // 累计拼接字符数字
                sum = sum * 10 + (ch - '0');
            } else if (ch != ' '){ // 过滤掉空格 只剩运算符
                stack.push(sum); // 遇到字符 把前面拼接的数字入栈
                sum = 0;                              // sum置0
                  // 栈不空 或者 当前运算符优先级 <= 栈顶运算符优先级
                while (!chStack.empty() &&
                   isBigger(chStack.peek(), ch)) { 
                   // 把数字栈顶两个数值弹出 进行运算
                   compute(stack, chStack.pop()); 
                }
                chStack.push(ch); // 当前运算符入 运算符栈
            }
        }
        stack.push(sum); // 最后一个数字 在for里计算之后没有入栈
        while (!chStack.empty()) {     // 最后计算剩下的数
            compute(stack, chStack.pop());
        }
        return stack.pop();
    }
    // 根据输入运算符ch  计算stack栈顶两个数
    void compute(Stack<Integer> stack, char ch) { 
         if (ch == '+') {
            stack.push(stack.pop() + stack.pop());
        } else if (ch == '-') { // 栈顶是减数,取反
            stack.push(-stack.pop() + stack.pop());
        } else if (ch == '*') {
            stack.push(stack.pop() * stack.pop());
        } else if (ch == '/') { 
            int num = stack.pop(); // 先临时保存栈顶(除数)
            stack.push(stack.pop() / num);
        }
    }
    // 运算符a的优先级 >= b的优先级  
    boolean isBigger(char a, char b) { 
        if (a == '/' || a == '*') return true; 
        if (b == '+' || b == '-') return true; // a b 是 +或者- 
        return false; // a 是+或-  b是*或者/
	}

方法2. 优化,只用数字栈

符号栈用一个变量sign代替了,只存储上一个符号,
注意,sign是当前数字前面的那个符号
比如:2+3*6  
遇到*的时候,这时判断sign是+,那么把3直接入栈,
因为前面是+,3后面运算优先级不会比它低,没有影响;
而当遇到*,/时,可以直接计算了,因为后面的优先级不会比它高了

同时,加 减 乘 除 空格 的ASCII码都小于'0',可以做判断条件
	public int calculate(String s) {
        if (s.length() == 0) return 0;
        Stack<Integer> numStk = new Stack<>();
        char sign = '+';// 保存上一个符号,初始为 +
        int sum = 0;// 保存当前数字,如:12是两个字符,需要进位累加
        for (int i = 0; i < s.length(); ++i) {
            char cur = s.charAt(i);
            if (cur >= '0') // +,-,*,/, 空格 ASCII码都<'0',可省略其他条件
                sum = sum * 10 - '0' + cur; // 先减'0',防止溢出
            
            // 注意!这里不能用else if,
            // 因为i到s末尾的时候,cur还是数字,不会进到下面计算
            // 同时,这里不能省略i到末尾的判断,
            // 如果要拿到for外面计算最后一个数字sum
            // 还要判断sign是什么,
            //进行最后一个sum的计算,不是直接把sum加入到numStk里
            if ((cur != ' ' && cur < '0')  || i == s.length() - 1){ 
                // 注意这里判断的是sign:当前数字sum的前面的符号,而不是cur
                if (sign == '+') numStk.push(sum);
                else if (sign == '-') numStk.push(-sum);
                else if (sign == '*') numStk.push(numStk.pop() * sum);
                else if (sign == '/') numStk.push(numStk.pop() / sum);
               
                sign = cur; // 符号更新
                sum = 0;// 数字清零
            }
        }
        sum = 0;
        // 将栈内剩余数字累加,即为结果
        while (!numStk.empty()) sum += numStk.pop();
        return sum;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值