LeetCode算法题(Go语言实现)_25

题目

给定一个整数数组 asteroids,表示在同一行的小行星。数组中小行星的索引表示它们在空间中的相对位置。
对于数组中的每一个元素,其绝对值表示小行星的大小,正负表示小行星的移动方向(正表示向右移动,负表示向左移动)。每一颗小行星以相同的速度移动。
找出碰撞后剩下的所有小行星。碰撞规则:两个小行星相互碰撞,较小的小行星会爆炸。如果两颗小行星大小相同,则两颗小行星都会爆炸。两颗移动方向相同的小行星,永远不会发生碰撞。

一、代码实现

func asteroidCollision(asteroids []int) []int {
    stack := make([]int, 0)
    for _, aster := range asteroids {
        alive := true // 标记当前小行星是否存活
        // 当栈顶行星向右,当前行星向左时触发碰撞检测
        for alive && len(stack) > 0 && aster < 0 && stack[len(stack)-1] > 0 {
            top := stack[len(stack)-1]
            if top > -aster { // 栈顶行星更大
                alive = false
            } else if top == -aster { // 同归于尽
                stack = stack[:len(stack)-1]
                alive = false
            } else { // 当前行星更大,栈顶爆炸
                stack = stack[:len(stack)-1]
            }
        }
        if alive {
            stack = append(stack, aster)
        }
    }
    return stack
}

二、算法分析

1. 核心思路
  • 栈结构特性:利用后进先出(LIFO)特性模拟碰撞顺序
  • 碰撞检测优化:仅在右向行星(正数)遇到左向行星(负数)时触发计算
2. 关键步骤
  1. 栈初始化:创建空栈存储存活行星
  2. 碰撞处理循环
    • 当栈顶行星向右且当前行星向左时进入碰撞判断
    • 比较大小决定爆炸情况(三种分支)
  3. 存活判断:未爆炸的行星入栈
3. 复杂度
指标说明
时间复杂度O(n)每个元素最多入栈、出栈各一次
空间复杂度O(n)栈存储最坏情况保存全部元素

三、图解示例

在这里插入图片描述

四、边界条件与扩展

1. 特殊场景验证
  • 全右向行星[1,5,3] → 直接返回原数组
  • 连续爆炸[10,2,-15][-15](2和10先后爆炸)
  • 边缘爆炸[1,1,-1,-1][](两对行星同归于尽)
2. 多语言实现
# Python实现(列表模拟栈)
def asteroidCollision(asteroids):
    stack = []
    for aster in asteroids:
        while stack and aster < 0 and stack[-1] > 0:
            if stack[-1] < -aster:
                stack.pop()
            elif stack[-1] == -aster:
                stack.pop()
                break
            else:
                break
        else:
            stack.append(aster)
    return stack
// Java实现(双端队列优化)
public int[] asteroidCollision(int[] asteroids) {
    Deque<Integer> stack = new ArrayDeque<>();
    for (int aster : asteroids) {
        boolean alive = true;
        while (!stack.isEmpty() && aster < 0 && stack.peekLast() > 0) {
            if (stack.peekLast() < -aster) {
                stack.pollLast();
            } else if (stack.peekLast() == -aster) {
                stack.pollLast();
                alive = false;
                break;
            } else {
                alive = false;
                break;
            }
        }
        if (alive) stack.addLast(aster);
    }
    return stack.stream().mapToInt(i->i).toArray();
}
3. 算法对比
方法时间复杂度空间复杂度优势
栈模拟法O(n)O(n)最优时间复杂度
暴力枚举法O(n²)O(1)仅适用于教学演示
递归回溯法O(2^n)O(n)理论价值大于实用价值

五、总结与扩展

1. 核心创新点
  • 动态碰撞检测:通过栈的实时更新实现高效碰撞模拟
  • 条件分支优化:仅处理右→左碰撞场景,降低计算复杂度
2. 数学本质

设总行星数n,碰撞次数k,则时间复杂度严格满足O(n+k),因k<n,最终复杂度为O(n)

3. 扩展应用
  • 括号匹配:处理嵌套结构时类似的栈操作逻辑
  • 交通流模拟:车辆变道冲突检测的离散事件模型
  • 游戏物理引擎:粒子碰撞检测的简化实现方案
  • 内存管理:类似malloc内存块的合并与分割操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值