快手 CodeTop LeetCode 224.基本计算器

思路:栈解法。用栈来处理括号带来的优先级问题,将复杂的表达式拆解成多个简单的、不带括号的子表达式分别计算。

1.解题过程:

(1)如果是数字字符'0' ~ '9',那么就连续读取数字,构建完整的数值。

(2)如果是加号'+',那么就将当前的数字累加到结果中,并重置符号为正(下一个数字是正数)。

(3)如果是减号'-',逻辑同加号,将当前的数字累加到结果中,并重置符号为负(下一个数字是负数)。

(4)如果是左括号'(',遇到左括号,先保存现场,然后重置符号。

(5)如果是右括号')',遇到右括号,先把括号内的数字和符号计算完毕,然后合并回括号前的现场。

(6)别忘了加上最后一个数字。

2.复杂度分析:

(1)时间复杂度:O(n)。

(2)空间复杂度:O(n)。

附代码:

java 复制代码
class Solution {
    public int calculate(String s) {
        LinkedList<Integer> stack = new LinkedList<>();
        // 当前已经计算好的结果
        int res = 0;
        // 当前数字前面的正负号
        int preSign = 1;
        // 当前正在读取的数字
        int num = 0;
        for (char c : s.toCharArray()) {
            // 遇到数字,连续读取数字构建完整的整数
            if (c <= '9' && c >= '0') {
                num = num * 10 + (c - '0');
            }
            // 遇到加号,把当前已读到数字累加到结果res
            // 然后重置已读数字num为0,重置符号为正(下一个数字是正数) 
            else if (c == '+') {
                res += num * preSign;
                num = 0;
                preSign = 1;
            }
            // 遇到减号,把当前已读到的数字累加到结果res
            // 然后重置已读数字num为0,重置符号为负(下一个数字是负数) 
            else if (c == '-') {
                res += num * preSign;
                num = 0;
                preSign = -1;
            }
            // 遇到左括号,先保存括号前的结果和括号前的符号入栈
            // 然后重置当前已经计算好的结果为0,以开始计算括号内的结果
            // 然后重置符号为正(括号内的第一个数字默认为正) 
            else if (c == '(') {
                stack.push(res);
                stack.push(preSign);
                res = 0;
                preSign = 1;
            }
            //  遇到右括号,加上括号内剩下的最后一个数字(因为遇到操作符才将当前数字加入结果,而最后一个数字没有遇到操作符,需要单独手动处理),然后括号里的数字已加减完毕
            // 然后乘上括号前的符号
            // 然后加上括号前的计算结果
            else if (c == ')') {
                res += num * preSign;
                // 括号外如果有数字会从新的num开始读取,否则最后return就是加个0,不会多加导致结果错误
                num = 0;
                // 这里不需要重置preSign
                // 因为遇到右括号代表括号内计算完毕,之后括号外的计算会使用从栈中弹出的符号,而不是preSign
                // 下一次遇到操作符时,根据之前的逻辑,也会会重新设置preSign
                res *= stack.pop();
                res += stack.pop();
            }
        }
        // 由于遇到操作符才将当前数字加入结果
        // 而最后一个数字没有遇到操作符
        // 因此需要单独手动处理
        return res + preSign * num;
    }
}

ACM模式:

java 复制代码
import java.util.LinkedList;
import java.util.Scanner;

class Solution {
    public int calculate(String s) {
        LinkedList<Integer> stack = new LinkedList<>();
        // 当前已经计算好的结果
        int res = 0;
        // 当前数字前面的正负号
        int preSign = 1;
        // 当前正在读取的数字
        int num = 0;

        for (char c : s.toCharArray()) {
            // 遇到数字,连续读取数字构建完整的整数
            if (c <= '9' && c >= '0') {
                num = num * 10 + (c - '0');
            }
            // 遇到加号,把当前已读到数字累加到结果res
            // 然后重置已读数字num为0,重置符号为正(下一个数字是正数)
            else if (c == '+') {
                res += num * preSign;
                num = 0;
                preSign = 1;
            }
            // 遇到减号,把当前已读到的数字累加到结果res
            // 然后重置已读数字num为0,重置符号为负(下一个数字是负数)
            else if (c == '-') {
                res += num * preSign;
                num = 0;
                preSign = -1;
            }
            // 遇到左括号,先保存括号前的结果和括号前的符号入栈
            // 然后重置当前已经计算好的结果为0,以开始计算括号内的结果
            // 然后重置符号为正(括号内的第一个数字默认为正)
            else if (c == '(') {
                stack.push(res);
                stack.push(preSign);
                res = 0;
                preSign = 1;
            }
            // 遇到右括号,加上括号内剩下的最后一个数字
            // 然后乘上括号前的符号,然后加上括号前的计算结果
            else if (c == ')') {
                res += num * preSign;
                // 括号外如果有数字会从新的num开始读取,否则最后return就是加个0,不会多加导致结果错误
                num = 0;
                // 这里不需要重置preSign
                // 因为遇到右括号代表括号内计算完毕,之后括号外的计算会使用从栈中弹出的符号,而不是preSign
                // 下一次遇到操作符时,根据之前的逻辑,也会会重新设置preSign
                res *= stack.pop();
                res += stack.pop();
            }
        }

        // 由于遇到操作符才将当前数字加入结果
        // 而最后一个数字没有遇到操作符,因此需要单独手动处理
        return res + preSign * num;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取表达式字符串(可能包含空格)
        String s = scanner.nextLine();

        // 计算结果
        Solution solution = new Solution();
        int result = solution.calculate(s);

        // 输出结果
        System.out.println(result);

        scanner.close();
    }
}
相关推荐
罗湖老棍子3 小时前
Biorhythms(信息学奥赛一本通- P1639)
算法·数论·裴蜀定理·扩展欧几里得·扩展中国剩余定理
奋发向前wcx8 小时前
CSP-J复赛模拟赛4 王晨旭补题 2026.10.5
算法
念何架构之路11 小时前
zap采样器与性能优化内幕
算法·性能优化·哈希算法
晒太羊的猫12 小时前
hot100动态规划刷题
算法·动态规划
weixin_5310946912 小时前
heap_4内存管理
java·开发语言·算法
余额瞒着我当琳12 小时前
红黑树的实现--红黑树的概念、规则、效率、结构、旋转、查找、验证
数据结构·c++·算法
程序员南飞12 小时前
win系统安装minio
java·数据结构·算法
青少儿编程课堂12 小时前
AC自动机多模式串匹配精讲:校园关键词巡检实战解析
c++·python·算法·bfs·信息学竞赛
longlongzihan13 小时前
LeetCode 5. 最长回文子串:从暴力匹配到中心扩展的思维演进
c++·算法·leetcode
waoooqwe13 小时前
问卷样本真实吗
大数据·数据库·算法·数据分析