Leetcode--Java--224. 基本计算器

题目描述

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

样例描述

示例 1:

输入:s = "1 + 1"
输出:2
示例 2:

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

输入:s = "(1+(4+5+2)-3)+(6+8)"
输出:23

思路

表达式求值 (通用模板题)
在这里插入图片描述

  1. 维护一个栈,如果遇到数就直接压入栈。遇到左括号也压入栈,遇到右括号将左括号之前的全算完。
  2. 遇到运算符的话,首先定义运算符的优先级如下,保证能够区分即可。
    在这里插入图片描述
    如果当前运算符优先级小于等于栈顶优先级,则计算栈顶,算完会有新的栈顶,然后压入栈中(继续比较然后计算,while循环过程)
    如果当前运算符大于栈顶优先级,则压入栈中。
    表达式求值的通用模板的整体流程如下:
    在这里插入图片描述
  3. 由于数和字符的类型不一样,需要用两个栈表示。一个存数,一个存运算符。
  4. 细节由于第一个数可能是负数,为了减少边界判断。先往 nums 添加一个 0。(也可以开始直接给s加个括号,然后变成下面的细节处理,在循环逻辑中处理掉)
  5. 细节防止 () 内出现的首个字符为运算符,将所有的空格去掉,并将 (- 替换为 (0-,(+ 替换为 (0+,在循环中处理这个细节。
  6. java函数名过长,为方便可以封装Character.isDigit这个方法,可以将字符串转化为字符数组方便索引里面的值。

代码

class Solution {
    
    
    Deque<Integer> nums = new LinkedList<>();
    Deque<Character> ops = new LinkedList<>();
    public int calculate(String s) {
    
    
        // //防止第一个数是负数,先加入一个0
        // nums.addLast(0);
        s = '(' + s + ')';
        //去掉字符串中所有空格
        s = s.replaceAll(" ", "");
        //转化为字符数组,方便索引字符
        char ch[] = s.toCharArray();
        int n = s.length();
        for (int i = 0; i < n; i ++ ) {
    
    
            char c = ch[i];
            //数的话,用双指针截取出数,并用字符串转数来求得这个数
            if (isNum(c)) {
    
    
                int j = i, num = 0;
               while (j < n && isNum(ch[j])) {
    
    
                   //转为int防止越界
                   num = num * 10 + (int)(ch[j ++] - '0');
               }
               i = j - 1; //类似双指针中,移动下标,j - 1因为循环还会移动1
               nums.addLast(num);
            } else if (c == '(') {
    
    
                ops.addLast(c);
            } //右括号的话,前面的直到最近的左括号都要计算完
            else if (c == ')') {
    
    
        
                  // 计算到最近一个左括号为止
                // while (!ops.isEmpty()) {
    
    
                //     char op = ops.peekLast();
                //     if (op != '(') {
    
    
                //         eval();
                //     } else {
    
    
                //         ops.pollLast();
                //         break;
                //     }
                // }
                while (ops.peekLast() != '(') eval();
                ops.pollLast();

                //  while (ops.peekLast() != '(') eval();
                //  //弹出左括号
                //  ops.pollLast();
            }    //对运算符
            else {
    
    
                // 特殊处理符号,如果前一个是(、+、-,当前又是运算符,就补一个0在中间
             if (i > 0 && (ch[i - 1] == '(' || ch[i - 1] == '+' || ch[i - 1] == '-')) 
               nums.addLast(0);

               //有新的操作符要入栈,由于这里没有优先级大小区分,就直接把栈内的都算了
            while (!ops.isEmpty() && ops.peekLast() != '(') {
    
    
                eval();
            }
            //算完后将新的操作符入栈
            ops.addLast(c);
            }
        }

        //防止还有没算完的,收尾
        while (!ops.isEmpty()) {
    
    
            eval();
        }
        return nums.peekLast();
    }
    //计算函数
    public void eval() {
    
    
        // //边界判断,数栈为空或者不足两个数,或者操作栈为空 直接返回
        //  if (nums.isEmpty() || nums.size() < 2) return;
        // if (ops.isEmpty()) return;

        //先弹出的是b,后弹出的是a,因为插入顺序与弹出的相反
        int b = nums.pollLast();
        int a = nums.pollLast();
        if (ops.pollLast() == '+') nums.addLast(a + b);
        else nums.addLast(a - b);
    }
    public boolean isNum(char c) {
    
    
        return Character.isDigit(c);
    }
}

猜你喜欢

转载自blog.csdn.net/Sherlock_Obama/article/details/121327742