227. 基本计算器 II

227. 基本计算器 II

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

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

示例 1:

输入: “3+2*2”
输出: 7
示例 2:

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

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

方法1

  • 总思路:全部转换为+号,把 *, / , - 都先计算出来,放到stack里,最后把stack里的数全部相加就是结果。

      // 遍历s的每个字符,如果是数字,和后面继续组成数字tempNum,
      //   并且根据前面的符号和数据,计算出结果放到stack中
      // 如果是'', 继续遍历
      // 如果是运算符号,更新lastOp
    
class Solution {
    public int calculate(String s) {
        Stack<Integer> numStack = new Stack<>();
        char[] arr = s.toCharArray();

        char lastOp = '+';

        for(int i = 0; i < arr.length; i++) {
            if(arr[i] == ' ') continue;

            if(Character.isDigit(arr[i])) {
                int tempNum = arr[i] - '0';
                while(++i < arr.length && Character.isDigit(arr[i])) {
                    tempNum = tempNum * 10 + (arr[i] - '0');
                }
                i--;

                if(lastOp == '+') numStack.push(tempNum);
                else if(lastOp == '-') numStack.push(-tempNum);
                else {
                    numStack.push(res(lastOp, numStack.pop(), tempNum));
                }
            }else {
                lastOp = arr[i];
            }
        }
        int ans = 0;
        for(int num : numStack) {
            ans += num;
        }

        return ans;
    }

    private int res(char lastOp, int num1, int num2) {
        int ans = 0;
        if(lastOp == '+') {  // '+' '-' 两种情况可以不写
            ans = num1 + num2;
        }else if(lastOp == '-') {
            ans = num1 - num2;
        }else if(lastOp == '*') {
            ans = num1 * num2;
        }else if(lastOp == '/') {
            ans = num1 / num2;
        }

        return ans;
    }
}

方法2
转换为后缀表达式
后缀表达式转换为

224. 基本计算器

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

字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。

示例 1:

输入: “1 + 1”
输出: 2
示例 2:

输入: " 2-1 + 2 "
输出: 3
示例 3:

输入: “(1+(4+5+2)-3)+(6+8)”
输出: 23

  • 增加了括号,括号可以递归计算

  • 再普通一点,加上乘法和除法

  • 和上一题思想类似,

  • 遍历字符串

  • 如果是数字,和后面的字符组成数字,再根据前面的符号计算结果,添加到栈中 ,即转换为加号

  • 如果字符是运算符,则

  • 问题来了,由于这题多了括号,而且添加了递归操作,就变得复杂起来。

  • 三个重点理解


  • 1.原来是数字,再根据前面的符号相加,添加到栈中,引到这里会出现问题:(1 + (4 + 5))中的(4 + 5)stack1递归回来后,num = 9, 要添加到(1)这层括号的stack0里,而此时递归回来后,ch = ‘(’, 如果按照上面的逻辑,这里不是数字,num=4+5就无法添加到stack0中;
  • 所以当ch为数字时,更新num;

  • 2.当ch不为数字时,操作num和op, 重点重中之重:eg:(1 * 1 + 1 ), 当遍历到 * 时,此时num = 1, op = + , ch = *, 搞清楚这三个变量之间的关系,执行:case ‘+’ : stack.push(num=1), num = 0; op = ch;
  • case ‘+’: 执行ch = ‘*’ 前面的数字操作,1 + ;添加到stack里
  • num = 0; 因为ch = ‘*’ , num要更新为0,具体数字取决于下一个ch
  • op = ch; 更新操作符,方便下一次遇到非数字+时,执行 + 前面的操作,执行 case ‘*’ : stack.push(stack.pop() * num);

  • eg: (1 + (4 - 5))
  • 3 递归:if(ch == ‘(’) {++i[0]; num = dfs(s, i);}
  • 执行完(4-5)后,回来时,ch = ‘(’, op = ‘+’; num = 4 - 5 = -1 ; 添加到stack0中;
  • 遇到‘)’ ,跳出循环,计算完(4-5)stack1中的数字,返回num = -1 给在stack0中的();

  • 4 为了一直遍历s, 不被递归的局部i打乱,这里i不止int型变量,而是int[] i = new int[1], 中的i[0], 即是对象,dfs(s, i) 是浅拷贝i, 即栈中的参数全部指向堆中的对象。

方法一:遍历字符,操作符转为加号,递归计算括号

class Solution {
    public int calculate(String s) {

        int[] i = new int[1];
        return dfs(s, i);
    }

    private int dfs(String s, int[] i) {
        Deque<Integer> stack = new LinkedList<>();
        int num = 0;
        char op = '+';

        for(; i[0] < s.length(); i[0]++) {
            
            char ch = s.charAt(i[0]);
            if(ch == '(') {
                ++i[0];
                num = dfs(s, i);
            }

            if(Character.isDigit(ch)) {
                num = num * 10 + (ch - '0');
            }

            if(!Character.isDigit(ch) && (ch != ' ') || i[0] == s.length() - 1) {
                switch(op) {
                    case '+':
                        stack.push(num); break;
                    case '-':
                        stack.push(-num); break;
                    case '*':
                        stack.push(stack.pop() * num);break;
                    case '/':
                        stack.push(stack.pop() / num);break;        
                }

                op = ch;
                num = 0;
            }

            if(ch == ')') {
                break;
            }
        }
        int res = 0;
        while(!stack.isEmpty()) {
            res += stack.pop();
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值