[Stack]行星碰撞

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 。
    
示例 4:
输入:asteroids = [-2,-1,1,2]
输出:[-2,-1,1,2]
解释:-2 和 -1 向左移动,而 1 和 2 向右移动。 由于移动方向相同的行星不会发生碰撞,所以最终没有行星发生碰撞。 

🔽 通过题目分析,可以遍历asteroids数组,然后用stack记录碰撞结果,碰撞结果该怎么分析呢?

  • 碰撞场景:
    • 如果栈顶元素是负数,无论当前元素正或者负,都不发生碰撞,可以直接入栈
    • 如果当前元素为正数,无论栈顶元素正或者负,都不发生碰撞,可以直接入栈
  • 通过碰撞场景分析可知,只有栈顶元素为正数并且当前元素为负数时,才会产生碰撞
    • 如果栈顶元素stack.peek()大于abs(asteroides[i]),当前元素不入栈
    • 如果栈顶元素stack.peek()等于abs(asteroides[i]),销毁栈顶元素,并且当前元素不入栈
    • 如果栈顶元素stack.peek()小于abs(asteroides[i]),栈顶弹出,并循环执行碰撞分析场景,循环完成后,当前元素入栈
public int[] asteroidCollision(int[] asteroids) {
    Deque<Integer> stack = new LinkedList<>();
    for (int asteroid : asteroids) {
        condition:
        {
            while (!stack.isEmpty() && asteroid < 0 && stack.peek() > 0) {
                if (stack.peek() > -asteroid) {
                    break condition;
                } else if (stack.peek() < -asteroid) {
                    stack.pop();
                    continue;
                } else if (stack.peek() == -asteroid) {
                    stack.pop();
                }
            }
        }
        stack.push(asteroid);
    }
    int[] ans = new int[stack.size()];
    for (int t = ans.length - 1; t >= 0; --t) {
        ans[t] = stack.pop();
    }
    return ans;
}

上述代码有break label的操作,可用通过设置boolean标记位达到同样的效果

// 模板代码
public void process(int[] array) {
    Deque<Integer> stack = new LinkedList<>();
    for (int num : array) {
        while (!stack.isEmpty()) {
            // coding logic
        }
        stack.push(num);
    }
}
posted @ 2021-12-19 16:28  __Helios  阅读(81)  评论(0编辑  收藏  举报