Drone Collisions Along a One-Dimensional Corridor
Solve this Problemarr gives one drone's launch speed and direction: positive means flying right, negative means flying left, and the magnitude is its size. Whenever a right-flying drone and a later left-flying drone meet, they collide: the smaller one is destroyed, or both are destroyed if they're equal in size. Two drones flying the same direction — or flying apart from each other — never meet. Return the sizes and directions of the drones left standing, in their original left-to-right order.
A single left-to-right pass with a stack of survivors handles every collision in one shot: a newly arriving drone only ever needs to fight the drone currently on top of the stack (the nearest survivor to its left), and if it wins, it keeps fighting whatever's now on top after that one's destroyed — a possible chain reaction — until it either loses, ties, or clears the stack entirely. Since each drone is pushed onto the stack once and can be popped off at most once for good, the whole simulation finishes in O(n), instead of the brute force's repeated O(n) rescans after every single collision.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ arr.length ≤ 12 - ◆
-100 ≤ arr[i] ≤ 100, and arr[i] ≠ 0 - ◆
A positive value means a drone flying right with that speed; a negative value means flying left, with size equal to |arr[i]| - ◆
All drones start moving at the same instant
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Repeatedly Rescan for the Next Collision
BruteKeep a working list of surviving drones. Repeatedly scan it from the beginning looking for the first adjacent pair still capable of colliding (a right-flier immediately followed by a left-flier). Resolve that one collision — removing the smaller drone, or both if they're equal in size — then restart the scan from the beginning, since removing drones can create brand-new adjacent pairs anywhere in the list. Keep going until a full scan finds no more colliding pairs. Correct, but each collision resolved can trigger a fresh O(n) scan, and there can be up to O(n) collisions, giving O(n²) overall.
O(n²)O(n)1class Solution {
2 public int[] simulateCollisions(int[] arr) {
3 List<Integer> list = new ArrayList<>();
4 for (int x : arr) list.add(x);
5 boolean changed = true;
6 while (changed) {
7 changed = false;
8 for (int i = 0; i < list.size() - 1; i++) {
9 if (list.get(i) > 0 && list.get(i + 1) < 0) {
10 int a = list.get(i), b = -list.get(i + 1);
11 if (a < b) {
12 list.remove(i);
13 } else if (a > b) {
14 list.remove(i + 1);
15 } else {
16 list.remove(i + 1);
17 list.remove(i);
18 }
19 changed = true;
20 break;
21 }
22 }
23 }
24 int[] result = new int[list.size()];
25 for (int i = 0; i < list.size(); i++) result[i] = list.get(i);
26 return result;
27 }
28}Optimal — Single-Pass Stack of Survivors
OptimalProcess drones left to right, keeping a stack of survivors seen so far. A new drone only ever collides with a right-flying drone currently on top of the stack, and only if the new drone itself flies left (any two drones moving the same direction, or moving apart, can never meet). Resolve that single collision immediately: if the stack's top is smaller, pop it and keep checking against what's now on top (a chain of destructions is possible); if they're equal, both are destroyed; if the stack's top is bigger, the new drone is destroyed and nothing changes below it. Once the new drone either survives or is destroyed, move to the next one. Each drone is pushed at most once and popped at most once, so total work is O(n).
O(n)O(n)1class Solution {
2 public int[] simulateCollisions(int[] arr) {
3 Deque<Integer> stack = new ArrayDeque<>();
4 for (int x : arr) {
5 boolean alive = true;
6 while (alive && x < 0 && !stack.isEmpty() && stack.peek() > 0) {
7 int top = stack.peek();
8 if (top < -x) {
9 stack.pop();
10 } else if (top == -x) {
11 stack.pop();
12 alive = false;
13 } else {
14 alive = false;
15 }
16 }
17 if (alive) stack.push(x);
18 }
19 int[] result = new int[stack.size()];
20 int i = result.length - 1;
21 for (int v : stack) result[i--] = v;
22 return result;
23 }
24}