☆打卡算法☆LeetCode 224. 基本计算器 算法解析

151 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情

推荐阅读

大家好,我是小魔龙,Unity3D软件工程师,VR、AR,虚拟仿真方向,不定时更新软件开发技巧,生活感悟,觉得有用记得一键三连哦。

一、题目

1、算法题目

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

题目链接:

来源:力扣(LeetCode)

链接: 224. 基本计算器 - 力扣(LeetCode)

2、题目描述

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

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

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

二、解题

1、思路分析

题意要求给定字符串表达式,实现基本计算器来计算并返回它的值。

这段字符串表达式,可能包含的元素有数字和括号、运算符加号和减号。

只有加减法,可以把括号全都展开来写,例如 2 - (1 - 3)展开成 2 - 1 + 3。

也就是,如果当前位置处于括号之内,则:

  • 遇到以 - 号开头的括号,此后的符号都要被翻转
  • 遇到以 + 号开头的括号,不变

可以考虑维护一个栈ops,栈顶元素存入根据括号所判断的符号sign:

  • 如果遇到+号,则更新sign ← ops.top()
  • 如果遇到-号,则更新sign ← -ops.top()

每当遇到左括号,则将当前的sign取值压入栈中。

每当遇到右括号,则从栈中弹出一个元素。

2、代码实现

代码参考:

class Solution {
    public int calculate(String s) {
        Deque<Integer> ops = new LinkedList<Integer>();
        ops.push(1);
        int sign = 1;

        int ret = 0;
        int n = s.length();
        int i = 0;
        while (i < n) {
            if (s.charAt(i) == ' ') {
                i++;
            } else if (s.charAt(i) == '+') {
                sign = ops.peek();
                i++;
            } else if (s.charAt(i) == '-') {
                sign = -ops.peek();
                i++;
            } else if (s.charAt(i) == '(') {
                ops.push(sign);
                i++;
            } else if (s.charAt(i) == ')') {
                ops.pop();
                i++;
            } else {
                long num = 0;
                while (i < n && Character.isDigit(s.charAt(i))) {
                    num = num * 10 + s.charAt(i) - '0';
                    i++;
                }
                ret += sign * num;
            }
        }
        return ret;
    }
}

image.png

3、时间复杂度

时间复杂度:O(n)

其中n为字符串s的长度,需要遍历字符串s一次,计算表达式的值。

空间复杂度:O(n)

其中n为字符串s的长度,空间复杂度屈取决于栈的空间,栈中的元素数量不超过n。

三、总结

本题基于栈这一数据结构可以演变出很多种解法。

比如使用双栈,一个栈存放所有的数字,一个栈存放所有数字意外的操作。

然后还是根据符号跟括号判断压入栈的元素。