快手 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();
    }
}
相关推荐
白白白小纯15 小时前
每日算法day3—回文链表,链表分割
c语言·数据结构·算法·leetcode
手写码匠16 小时前
华为云Flexus+DeepSeek征文|Dify 构建企业级联网搜索 Agent:查询改写、多源检索与引用溯源实战
人工智能·深度学习·算法·aigc
七夜zippoe16 小时前
DolphinDB 能耗统计分析实战:报表生成、同比环比与定额对比
人工智能·算法·dolphindb·报表生成·能耗统计·定额对比
为啥全要学16 小时前
在大语言模型上使用 PPO 算法
人工智能·算法·语言模型
zander25816 小时前
35. 搜索插入位置:从边界语义理解二分查找
数据结构·算法·leetcode
汤愈韬16 小时前
模型求解算法
人工智能·算法·机器学习
Keven_1117 小时前
算法札记:DP中的滚动数组
算法·滚动数组
luj_176817 小时前
随机性在算法与占卜中的共通原理
c语言·开发语言·c++·经验分享·算法
yyds_yyd_1008617 小时前
3731. 找出缺失的元素(2026.08.04)
c++·leetcode
Chen—LSN17 小时前
C语言——深度理解指针(5)
c语言·数据结构·算法·排序算法