图解LeetCode——735. 行星碰撞(难度:中等)

一、题目

给定一个整数数组 asteroids,表示在同一行(一条水平线,并非一个圆圈) 的行星,。

对于数组中的每一个元素,其绝对值表示行星的大小,正负表示行星的移动方向(正表示向右移动,负表示向左移动)。每一颗行星以相同的速度移动。请找出碰撞后剩下的所有行星。

碰撞规则如下所示:

两个行星相互碰撞,较小的行星会爆炸。如果两颗行星大小相同,则两颗行星都会爆炸。两颗移动方向相同的行星,永远不会发生碰撞

二、示例

示例 1:

【输入】asteroids = [5,10,-5]
【输出】[5,10]
【解释】10 和 -5 碰撞后只剩下 10 。 5 和 10 永远不会发生碰撞。

示例 2:

【输入】asteroids = [8,-8]
【输出】[]
【解释】8 和 -8 碰撞后,两者都发生爆炸。

示例 3:

【输入】asteroids = [10,2,-5]
【输出】[10]
【解释】2 和 -5 发生碰撞后剩下 -5 。10 和 -5 发生碰撞后剩下 10 。

提示:

  • • 2 <= asteroids.length <= 104
  • • -1000 <= asteroids[i] <= 1000
  • • asteroids[i] != 0

三、解题思路

这道题如果我们借助堆栈结构的话,就会很好的实现。因为题中描述了一个重要的点,那就是正数的行星向右行进,负数的行星向左行进。那么也就是说,只有当正数行星在负数行星左侧时,两者才会相撞。如下所示:

6583f475d06b44720abf6979a641c969.png

通过上面的四种情况,我们其实只需要关注【情况四】就可以了,也就是说,当从堆栈中pop出一个元素是正数,并且待放入的元素是负数的时候,才会发生对比碰撞操作;否则其他情况下,就是向堆栈中放入元素即可。

如下我们以asteroids = [-2, 1, -1, -2] 为例,通过图形演示一下具体的处理过程。首先:由于stack中是空的,所以第一个元素-2可以顺利进入堆栈中。如下所示:

6d5dbecd2d22f288e826fdef1e45f3db.png

步骤2:我们要插入第二个元素1,因为-2与1的关系符合“情况3”,无法形成碰撞,所以将1放入stack中。如下所示:

7365088231be5c30d3e6d95badba7552.png

步骤3:我们要插入第三个元素-1,因为1与-1的关系符合“情况4”,发生碰撞,因为值相同,所以同时毁灭。即:1出栈,-1不进栈。如下所示:

0656cc091e5baf33cf11c29bb3ec9f48.png

步骤4:我们要插入第四个元素-2,因为-2与-2的关系符合“情况2”,无法形成碰撞,所以将-2放入stack中。如下所示:

14763af56ddefb43a4cdcbaf086c00c9.png

综上所述,最终输出的结果就是[-2, -2]

四、代码实现

class Solution {
    public int[] asteroidCollision(int[] asteroids) {
        // 利用队列模拟堆栈,用Deque比Stack速度快了5倍(10ms——>2ms)
        Deque<Integer> stack = new ArrayDeque(); 
        
        for (int i = 0; i < asteroids.length; i++) {
            int num;
            boolean insert = true;
            while (!stack.isEmpty() && stack.peek() >= 0 && asteroids[i] < 0 && (insert = (stack.peek() + asteroids[i] <= 0))) {
                num = stack.pop(); // 被毁掉
                if (num + asteroids[i] == 0) {
                    insert = false;
                    break;
                }
            }

            // 判断asteroids[i]是否可以进入堆栈中
            if (insert) {
                stack.push(asteroids[i]);
            } 
        }

        // 将stack转换为int[],作为结果进行输出
        int[] result = new int[stack.size()];
        for (int i = stack.size() - 1; i >= 0; i--) {
            result[i] = stack.pop();
        }

        return result;
    }
}

今天的文章内容就这些了,最后一句话:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的点赞&分享

更多技术干活,欢迎大家关注公众号“爪哇缪斯”(^o^)/~ 「干货分享,每周更新」

往期精选

题目来源:力扣(LeetCode)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值