leetcode
leetcode 601 ~ 650
小行星碰撞

小行星碰撞

难度:

标签:

题目描述

代码结果

运行时间: 24 ms, 内存: 17.0 MB


/*
 * 思路:
 * 使用Stack存储行星。对于每个小行星,如果是负数且栈顶是正数,则表示可能发生碰撞。否则直接入栈。
 * 使用Stream生成最终结果。
 */
import java.util.Stack;
import java.util.Arrays;
 
public class AsteroidCollisionStream {
    public int[] asteroidCollision(int[] asteroids) {
        Stack<Integer> stack = new Stack<>();
        Arrays.stream(asteroids).forEach(asteroid -> {
            boolean alive = true;
            while (alive && !stack.isEmpty() && stack.peek() > 0 && asteroid < 0) {
                int top = stack.pop();
                if (top + asteroid == 0) {
                    alive = false; // both explode
                } else if (top + asteroid > 0) {
                    asteroid = top; // top survives
                } // else, asteroid survives (keep alive = true)
            }
            if (alive) stack.push(asteroid);
        });
        return stack.stream().mapToInt(i -> i).toArray();
    }
}

解释

方法:

这个题解使用了栈的数据结构。遍历给定的小行星数组,对于每个小行星,根据其运动方向和栈顶小行星的情况进行处理。如果当前小行星向右运动(正数),直接将其压入栈中;如果向左运动(负数),则与栈顶的小行星进行比较。如果栈顶小行星向右运动且体积更大,则弹出栈顶小行星,继续比较,直到栈为空或者当前小行星体积更大。如果最终栈为空或者当前小行星存活,则将当前小行星压入栈中。遍历完整个数组后,栈中剩余的小行星即为碰撞后存活的小行星。

时间复杂度:

O(n^2),其中 n 是数组的长度,但平均情况下接近 O(n)。

空间复杂度:

O(n),其中 n 是数组的长度。

代码细节讲解

🦆
为什么选择使用栈结构来解决这个问题,栈有哪些特性使其适合处理小行星碰撞的场景?
栈是一种后进先出(LIFO)的数据结构,适合处理需要回溯元素以进行比较和决策的问题。在小行星碰撞的场景中,当新的小行星进入时,我们需要与之前的小行星比较并决定是否爆炸。这种比较和决策过程需要从最近的小行星开始,依次向前,直到找到决策点。栈允许我们方便地访问最后进入的小行星,并根据碰撞规则逐个处理,这符合问题的自然处理顺序。
🦆
如果小行星数组中所有元素都是负数,算法的行为会有什么不同?
如果小行星数组中的所有元素都是负数,这意味着所有小行星都向左运动。在这种情况下,由于没有向右运动的小行星与之相撞,所有这些向左运动的小行星将直接被添加到栈中,不会发生任何碰撞。结果,栈中最终将包含数组中的所有小行星,按照它们在数组中的顺序。
🦆
解题思路中提到,如果栈顶小行星向右运动且体积更小,则栈顶小行星爆炸。这里为何不考虑当前向左运动的小行星也可能爆炸的情况?
在题解中,如果当前向左运动的小行星体积大于栈顶向右运动的小行星体积,栈顶小行星会爆炸,然后继续比较下一个栈顶小行星。这个过程会持续,直到找到一个更大的向右运动的小行星或栈为空。如果栈为空或没有足够大的向右运动小行星来停止当前向左运动的小行星,那么该向左运动的小行星将被添加到栈中。因此,当前向左运动的小行星只有在面对更大的对立小行星时才会'爆炸',否则它会存活并最终被添加到栈中。
🦆
在处理小行星碰撞的过程中,如果遇到栈顶小行星体积与当前小行星体积相等且相反方向的情况,为何选择直接将两者都爆炸而不保留任何一方?
当栈顶小行星和当前小行星体积相等且方向相反时,根据物理碰撞的模拟,两者都将完全相互抵消。这种情况下,选择让两者都爆炸是为了模拟现实中的完全能量抵消现象。保留任何一方都将违反题目的碰撞逻辑,即两个体积相等且方向相反的物体在碰撞后都应该消失。这样的处理简化了逻辑并保持了问题描述的一致性。

相关问题

种花问题

假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

给你一个整数数组 flowerbed 表示花坛,由若干 01 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false 。

 

示例 1:

输入:flowerbed = [1,0,0,0,1], n = 1
输出:true

示例 2:

输入:flowerbed = [1,0,0,0,1], n = 2
输出:false

 

提示:

  • 1 <= flowerbed.length <= 2 * 104
  • flowerbed[i]01
  • flowerbed 中不存在相邻的两朵花
  • 0 <= n <= flowerbed.length