多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

AlgoNote 算法通关手册:LeetCode 0735 小行星碰撞——用栈模拟同向运动中的碰撞过程

AlgoNote 算法通关手册:LeetCode 0735 小行星碰撞——用栈模拟同向运动中的碰撞过程 教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载导读本文讲解 LeetCode 0735「小行星碰撞」题目的完整解法。这是一道典型的「栈 数组」模拟类中等题核心在于利用栈的后进先出LIFO特性模拟一排小行星同向运动时发生的连续碰撞。读完本文你将掌握如何用单一栈在 O(n) 时间内完成「按方向成对消除」类问题的建模并能举一反三地解决括号匹配、行星碰撞LCR 037等同族问题。题目解读同一行的小行星如何碰撞题目大意给定一个整数数组asteroids表示在同一行运动的小行星每个元素的绝对值表示小行星的大小每个元素的正负号表示小行星的移动方向正数向右移动负数向左移动每一颗小行星以相同的速度移动。碰撞规则只有三条两个行星相互碰撞时较小的行星会爆炸消失如果两颗行星大小相同则两颗都会爆炸消失两颗移动方向相同的行星永远不会发生碰撞。要求找出碰撞后剩下的所有小行星将答案存入数组并返回。由于所有小行星速度相同、位于同一行真正可能相遇的只有一种组合向右移动的小行星正数在前向左移动的小行星负数在后——即数组中「正数出现在负数左侧」时两者必然相向而行并发生碰撞。为什么用栈碰撞只发生在「紧邻」的小行星之间碰撞的天然特征是只发生在相邻紧挨着的相向小行星之间而且一次碰撞后幸存下来的小行星还会继续与更前面的小行星发生连锁碰撞。这种「后发生的碰撞取决于之前的结果、且总是从最近处开始」的过程正是栈结构最擅长的场景栈顶始终是「当前最靠右、尚未被消灭」的小行星也就是下一次碰撞的候选者出栈pop对应「小行星被撞爆炸」入栈push对应「小行星幸存并继续存在」。这与 AlgoNote 算法通关手册中栈基础章节介绍的栈特性完全一致栈只允许在栈顶进行插入和删除遵循**后进先出LIFO**原则非常适合处理「只关心最近一个元素、且需要回溯历史状态」的模拟问题。解题思路单栈模拟碰撞全过程用栈模拟小行星碰撞具体步骤如下遍历数组asteroids逐个处理小行星。入栈条件如果栈为空或者当前元素asteroid为正数向右移动直接将其压入栈。因为正数向右移动不会与栈中左侧的任何行星相撞左侧行星要么向左移动、要么同向右移动均不会迎面相遇。碰撞条件如果当前栈不为空且当前元素asteroid为负数向左移动说明它可能与栈中的行星相撞连续碰撞只要栈顶元素为正数并且当前元素的绝对值大于栈顶元素0 stack[-1] -asteroid就把栈顶元素弹出——栈顶的右向小行星被撞爆炸负向小行星继续前进与新的栈顶继续碰撞。幸存入栈碰撞结束后如果栈为空或者栈顶元素为负数说明当前负向小行星一路撞穿了所有右向行星或者原本左侧就没有右向行星则将当前元素asteroid压入栈表示碰撞后它幸存了下来。同归于尽如果栈顶元素恰好与当前元素值大小相等、方向相反stack[-1] -asteroid则弹出栈顶元素表示碰撞后两者都爆炸了当前负向小行星也不入栈。返回答案遍历结束后栈中剩下的元素就是所有碰撞后幸存的小行星直接返回栈即可。分步模拟示例以asteroids [5, 10, -5]为例步骤当前元素操作栈状态左为栈底15栈空直接入栈[5]210正数直接入栈[5, 10]3-5栈顶10的绝对值大于5-5被撞爆炸[5, 10]结果为[5, 10]。再看一个发生连锁碰撞的例子asteroids [10, 2, -5]步骤当前元素操作栈状态左为栈底110栈空直接入栈[10]22正数直接入栈[10, 2]3-52被撞爆炸2 5继续与10比较10 5-5爆炸[10]结果为[10]这里体现了「负向小行星撞穿一个正数后仍不敌更靠左的更大行星」的连续碰撞逻辑。再验证「同归于尽」分支asteroids [8, -8]步骤当前元素操作栈状态左为栈底18栈空直接入栈[8]2-8大小相等、方向相反两者都爆炸[]结果为[]。代码实现原文档给出的完整实现如下class Solution: def asteroidCollision(self, asteroids: List[int]) - List[int]: stack [] for asteroid in asteroids: if not stack or asteroid 0: stack.append(asteroid) else: while stack and 0 stack[-1] -asteroid: stack.pop() if not stack or stack[-1] 0: stack.append(asteroid) elif stack[-1] -asteroid: stack.pop() return stack关键代码逐行解读while stack and 0 stack[-1] -asteroid这是整个算法的核心。0 stack[-1]保证栈顶是向右移动的正数只有正数才会与当前负数相撞stack[-1] -asteroid等价于「栈顶大小 当前行星大小」即当前负向小行星更大撞毁栈顶后继续前进。循环结束后有三种可能栈为空或栈顶为负数 → 当前小行星幸存stack.append(asteroid)栈顶正数与当前行星大小相等 →stack.pop()两者同归于尽栈顶正数大于当前行星 → 当前行星被撞爆炸不入栈也不弹栈。复杂度分析时间复杂度O(n)。每个小行星最多入栈一次、出栈一次虽然内层有while循环但所有元素的总出栈次数不超过 n 次因此整体仍是线性时间。空间复杂度O(n)。最坏情况下如所有行星同向运动、互不碰撞栈中需要保存全部 n 个元素。从仓库源码看栈的底层实现本解法中的stack []在 Python 中本质是一个基于列表的顺序栈。仓库中的顺序栈实现示例清晰地展示了其底层机制class Stack: # 初始化空栈 def __init__(self, size100): self.stack [] self.size size self.top -1 # 入栈操作 def push(self, value): if self.is_full(): raise Exception(Stack is full) else: self.stack.append(value) self.top 1 # 出栈操作 def pop(self): if self.is_empty(): raise Exception(Stack is empty) else: self.top - 1 self.stack.pop() # 获取栈顶元素 def peek(self): if self.is_empty(): raise Exception(Stack is empty) else: return self.stack[self.top]可以看到push对应列表的append尾部追加pop对应列表的pop()尾部弹出peek对应stack[-1]访问栈顶。小行星碰撞解法正是直接使用 Python 列表的这三个 O(1) 操作完成栈模拟无需自定义栈类。更完整的顺序栈与链式栈对比可参考栈基础章节。此外本题虽然不属于严格意义的单调栈问题但「用栈顶与当前元素反复比较、不合条件即弹出」的过程与单调栈章节描述的「进栈时弹出所有不满足单调性的元素」的思想一脉相承——区别在于本题弹出条件还受「方向」和「大小比较」双重约束。题目变式与同类练习本题在仓库中还有一道几乎完全一致的变式题LCR 037. 行星碰撞力扣 LCR 037题面与解题思路、代码完全一致可作为本解的交叉验证。掌握「栈模拟按方向成对消除」这一类题型后可以继续挑战仓库中以下同族题目0020. 有效的括号用栈匹配成对出现的括号是栈模拟的入门经典0155. 最小栈栈在 O(1) 时间内维护额外信息0150. 逆波兰表达式求值用栈对操作数做运算0739. 每日温度单调栈求右侧第一个更大元素与本题「栈顶比较弹出」的模式最为接近0394. 字符串解码栈处理嵌套结构。本题在算法面试热门题目总表中被标注为「栈、数组、模拟中等」难度与每日温度同属 0700-0799 区间内的栈类模拟题适合在掌握栈基础后作为进阶练习。小结LeetCode 0735「小行星碰撞」的精髓在于识别出「碰撞只发生在相邻相向小行星之间、且存在连锁反应」这一结构从而自然联想到用栈维护「尚未被消灭的最近行星」。只需一次线性遍历配合三条清晰的入栈/出栈判定规则即可在 O(n) 时间内得到所有幸存小行星。把这道题的「方向 大小」双重判定逻辑吃透栈模拟类的面试题基本可以一通百通。赞分享教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载相关推荐DialoGPT-medium-joshua-openmind常见问题解答新手入门必知的10个要点DialoGPT medium joshua openmind常见问题解答新手入门必知的10个要点 DialoGPT medium joshua openmiLeetCode 0015 三数之和排序 对撞指针全解AlgoNote 算法通关手册LeetCode 0015 三数之和排序 对撞指针全解AlgoNote 算法通关手册 本文是「算法通关手册」AlgoNote中 0015. 三数之教程文档知识库AlgoNote 算法通关手册题解LeetCode 0636 函数的独占时间——用栈模拟单线程 CPU 调用过程AlgoNote 算法通关手册题解LeetCode 0636 函数的独占时间——用栈模拟单线程 CPU 调用过程 导读 本文是「算法通关手册」中 LeetCo教程文档知识库上一篇PHPWord Bookmark 书签元素完全指南在 Word/ODT 文档中定位与内部跳转下一篇KernelSU 怎么装四个真实场景带你走完 KernelSU 安装全流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表