Talentd
FleetCode
Make and follow sheets.Sign in

Robot Collisions solution and explanation

HardArraySimulationSortingStack8 min read61.6% acceptanceUpdated 9 Apr 2026
Robot Collisions | Made Easy | Dry Run | Leetcode 2751 | codestorywithMIKcodestorywithMIK · 35:30 · 16K viewsWatch on YouTube
9 more videos on this problem
  1. Robot Collisions | Made Easy | Dry Run | Leetcode 2751 | codestorywithMIKcodestorywithMIK · 35:30 · 16K views
  2. Robot Collisions - Leetcode 2751 - PythonNeetCodeIO · 19:47 · 12K views
  3. 2751. Robot Collisions | Stack | Sorting | Not Hard 🫡Aryan Mittal · 19:30 · 7K views
  4. ✅ Robot Collisions - LeetCode 2751 - Sorting - Optimized - Explained in Detail with ExamplesLeet Logics · 16:21 · 659 views
  5. LeetCode 2751 | Robot Collision | Reduction | StackBot George · 18:37 · 600 views
  6. 2751. Robot Collisions | Leetcode Daily - PythonLeetcode Daily · 4:26 · 546 views
  7. Leetcode 2751. Robot Collisions Visual Explanation (Stack Simulation)Code Crusaders · 5:28 · 468 views
  8. Robot Collisions | Leetcode 2751 | Java | Hindi | Daily LeetcodeKernel Queen 👑 · 11:32 · 415 views
  9. 2751. Robot Collisions (Leetcode Hard)Programming Live with Larry · 38:53 · 371 views
  10. Robot Collisions - LeetCode 2751- PythonAlpha-Code · 19:22 · 189 views

The problem

There are n 1-indexed robots, each having a position on a line, health, and movement direction.

You are given 0-indexed integer arrays positions, healths, and a string directions (directions[i] is either 'L' for left or 'R' for right). All integers in positions are unique.

All robots start moving on the line simultaneously at the same speed in their given directions. If two robots ever share the same position while moving, they will collide.

If two robots collide, the robot with lower health is removed from the line, and the health of the other robot decreases by one. The surviving robot continues in the same direction it was going. If both robots have the same health, they are both removed from the line.

Your task is to determine the health of the robots that survive the collisions, in the same order that the robots were given, i.e. final health of robot 1 (if survived), final health of robot 2 (if survived), and so on. If there are no survivors, return an empty array.

Return an array containing the health of the remaining robots (in the order they were given in the input), after no further collisions can occur.

Note: The positions may be unsorted.

 

Example 1:

Input: positions = [5,4,3,2,1], healths = [2,17,9,15,10], directions = "RRRRR"
Output: [2,17,9,15,10]
Explanation: No collision occurs in this example, since all robots are moving in the same direction. So, the health of the robots in order from the first robot is returned, [2, 17, 9, 15, 10].

Example 2:

Input: positions = [3,5,2,6], healths = [10,10,15,12], directions = "RLRL"
Output: [14]
Explanation: There are 2 collisions in this example. Firstly, robot 1 and robot 2 will collide, and since both have the same health, they will be removed from the line. Next, robot 3 and robot 4 will collide and since robot 4's health is smaller, it gets removed, and robot 3's health becomes 15 - 1 = 14. Only robot 3 remains, so we return [14].

Example 3:

Input: positions = [1,2,5,6], healths = [10,10,11,11], directions = "RLRL"
Output: []
Explanation: Robot 1 and robot 2 will collide and since both have the same health, they are both removed. Robot 3 and 4 will collide and since both have the same health, they are both removed. So, we return an empty array, [].

Constraints:

  • 1 <= positions.length == healths.length == directions.length == n <= 105
  • 1 <= positions[i], healths[i] <= 109
  • directions[i] == 'L' or directions[i] == 'R'
  • All values in positions are distinct

Approach overview

Problem Overview: You are given robots on a number line with positions, health values, and directions (L or R). Robots moving toward each other collide. The robot with lower health is destroyed, and the winner loses one health. The task is to simulate all collisions and return the remaining health values of surviving robots in their original order.

Approach 1: Sorting and Stack-based Collision Detection (O(n log n) time, O(n) space)

Robots interact based on their positions, not their input order. The first step is to sort robot indices by position using sorting. After sorting, iterate from left to right. Maintain a stack that stores indices of robots moving to the right (R). When you encounter a robot moving left (L), it may collide with robots stored in the stack.

Resolve collisions using a loop. Compare the current robot's health with the robot on top of the stack. The robot with smaller health is removed. The survivor loses one health and may continue colliding with the next robot. If both have equal health, both are destroyed. This pattern is a classic use of a stack to simulate pairwise interactions. Each robot is pushed and popped at most once, so the collision processing itself is linear.

The overall complexity is O(n log n) due to sorting by position, while the stack simulation runs in O(n). Space complexity is O(n) for storing robot indices and survivors. This approach is the most intuitive and closely mirrors how the physical simulation works.

Approach 2: Two-Pointer Collision Simulation (O(n log n) time, O(n) space)

Another way to model the system is to first sort robots by position and then simulate interactions using two directional scans. After sorting, track right-moving robots and resolve collisions when a left-moving robot appears. Instead of an explicit stack structure, pointers track the most recent active right-moving robot that could collide with the current left-moving robot.

The algorithm repeatedly compares the current robot with the nearest opposing robot and applies the same health reduction rules used in the simulation. When a robot is destroyed, pointers advance to the next possible candidate. This technique keeps the logic iterative and avoids explicit stack operations, though conceptually it still represents the same collision frontier.

The runtime remains O(n log n) because sorting dominates the cost. The simulation step processes each robot a constant number of times, giving O(n) additional work. Space complexity is O(n) for storing sorted indices and tracking robot states.

Recommended for interviews: The sorting + stack approach is the most expected solution. It clearly models collisions and demonstrates understanding of monotonic interaction patterns similar to asteroid collision problems. Starting with a naive simulation shows understanding of the rules, but implementing the stack-based collision resolution signals strong algorithmic reasoning.

Approach 1: Sorting and Stack-based Collision Detection

This approach involves sorting the robots based on their positions so that we can simulate their movements along the line. We utilize a stack to keep track of the robots moving rightward. When a robot moving left encounters one or more robots on the stack, a collision is detected, and their healths are compared to determine the outcome.

def surviving_robots_health(positions, healths, directions):
    robots = sorted(zip(positions, healths, directions, range(len(positions))), key=lambda x: x[0])
    survivors = [True] * len(robots)
    stack = []  # this will store indices of robots moving 'R'

    for _, health, direction, index in robots:
        if direction == 'R':
            stack.append((health, index))
        else:
            while stack and stack[-1][0] < health:
                health -= 1
                prev_health, prev_index = stack.pop()
                survivors[prev_index] = False
            if stack:
                if stack[-1][0] == health:
                    survivors[stack.pop()[1]] = False
                    survivors[index] = False
                else:
                    stack[-1] = (stack[-1][0] - 1, stack[-1][1])
                    survivors[index] = False

    return [h for (_, h, _, i), s in zip(robots, survivors) if s]
import java.util.*;

class RobotCollision {
    public List<Integer> survivingRobotsHealth(int[] positions, int[] healths, String directions) {
        int n = positions.length;
        Integer[] indices = new Integer[n];
        for (int i = 0; i < n; i++) indices[i] = i;
        Arrays.sort(indices, Comparator.comparingInt(i -> positions[i]));

        List<Integer> result = new ArrayList<>();
        Deque<Integer> stack = new ArrayDeque<>();

        boolean[] survivor = new boolean[n];
        Arrays.fill(survivor, true);

        for (int idx : indices) {
            if (directions.charAt(idx) == 'R') {
                stack.push(idx);
            } else {
                while (!stack.isEmpty() && healths[stack.peek()] < healths[idx]) {
                    int rIdx = stack.pop();
                    healths[idx]--;
                    survivor[rIdx] = false;
                }
                if (!stack.isEmpty() && healths[stack.peek()] == healths[idx]) {
                    survivor[stack.pop()] = false;
                    survivor[idx] = false;
                } else if (!stack.isEmpty()) {
                    healths[stack.peek()]--;
                    survivor[idx] = false;
                }
            }
        }

        for (int i = 0; i < n; i++) {
            if (survivor[i]) {
                result.add(healths[i]);
            }
        }

        return result;
    }
}

The function first combines the input into a list of tuples and sorts it based on positions. For each robot, if it's moving right, its index is pushed onto a stack. When a left-moving robot encounters right-moving ones, collisions occur, and appropriate robots are removed based on their healths.

Complexity

Time Complexity: O(n log n) due to sorting the list of robots.
Space Complexity: O(n) because of the additional data structures used (stack and survivor list).

Try this approach in the editor

Approach 2: Two-Pointer Collision Simulation

This approach simulates the collision process using a two-pointer technique. Each pointer represents a different direction of movement. By carefully checking each pair of robots, we can simulate their interactions and resolve collisions by adjusting health values and determining survivors.

function survivingRobotsHealth(positions, healths, directions) {
  let n = positions.length;
  let robots = directions.split('').map((d, i) => ({ pos: positions[i], health: healths[i], dir: d, idx: i }));

  robots.sort((a, b) => a.pos - b.pos);
  let survivors = Array(n).fill(true);
  let stack = [];

  robots.forEach(({ dir, health, idx }, i) => {
    if (dir === 'R') {
      stack.push({ health, idx });
    } else {
      while (stack.length > 0 && stack[stack.length - 1].health < health) {
        health -= 1;
        let top = stack.pop();
        survivors[top.idx] = false;
      }
      if (stack.length > 0 && stack[stack.length - 1].health === health) {
        survivors[stack.pop().idx] = false;
        survivors[idx] = false;
      } else if (stack.length > 0) {
        stack[stack.length - 1].health -= 1;
        survivors[idx] = false;
      }
    }
  });

  return robots.filter(({ idx }) => survivors[idx]).map(({ health }) => health);
}
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct { int pos, health, idx; char dir; } Robot;

int compare(const void* a, const void* b) {
    return ((Robot*)a)->pos - ((Robot*)b)->pos;
}

int* survivingRobotsHealth(int* positions, int positionsSize, int* healths, char* directions, int* returnSize) {
    Robot* robots = malloc(positionsSize * sizeof(Robot));
    bool* survivors = malloc(positionsSize * sizeof(bool));
    for (int i = 0; i < positionsSize; i++) {
        robots[i] = (Robot){positions[i], healths[i], i, directions[i] };
        survivors[i] = true;
    }
    qsort(robots, positionsSize, sizeof(Robot), compare);

    int* stack = malloc(positionsSize * sizeof(int));
    int top = -1;

    for (int i = 0; i < positionsSize; i++) {
        if (robots[i].dir == 'R') {
            stack[++top] = i;
        }
        else {
            while (top >= 0 && robots[stack[top]].health < robots[i].health) {
                robots[i].health -= 1;
                survivors[robots[stack[top]--].idx] = false;
            }
            if (top >= 0 && robots[stack[top]].health == robots[i].health) {
                survivors[robots[stack[top--]].idx] = false;
                survivors[robots[i].idx] = false;
            } else if (top >= 0) {
                robots[stack[top]].health -= 1;
                survivors[robots[i].idx] = false;
            }
        }
    }

    int* result = malloc(positionsSize * sizeof(int));
    int count = 0;
    for (int i = 0; i < positionsSize; i++) {
        if (survivors[robots[i].idx]) {
            result[count++] = robots[i].health;
        }
    }

    *returnSize = count;
    free(robots);
    free(survivors);
    free(stack);
    return result;
}

This solution leverages a two-pointer-like mechanism where rightward-moving robots are managed with a stack. As each leftward-moving robot approaches, they are compared against the stack, with resulting health and survival adjustments.

Complexity

Time Complexity: O(n log n) due to sorting the positions.
Space Complexity: O(n) due to extra data structures for handling collisions.

Try this approach in the editor

Approach 3: Default Approach

We first sort the robots by position in ascending order, storing the sorted robot indices in an array idx. We then use a stack to simulate the collision process:

  1. Traverse the robot indices i in idx from left to right. If directions[i] is moving right, push i onto the stack.
  2. If directions[i] is moving left, it collides with the right-moving robot at the top of the stack, until the stack is empty or the current robot is removed.
    • If the top robot's health is greater than the current robot's, the current robot is removed and the top robot's health decreases by 1.
    • If the top robot's health is less than the current robot's, the top robot is removed, the current robot's health decreases by 1, and the current robot continues to collide with the new top robot.
    • If both have equal health, both are removed.

Finally, we return the health values of all robots with health greater than 0.

The time complexity is O(n times log n) and the space complexity is O(n), where n is the number of robots.

class Solution {
public:
    vector<int> survivedRobotsHealths(vector<int>& positions, vector<int>& healths, string directions) {
        int n = positions.size();
        vector<int> idx(n);
        iota(idx.begin(), idx.end(), 0);

        sort(idx.begin(), idx.end(), [&](int a, int b) {
            return positions[a] < positions[b];
        });

        vector<int> stk;

        for (int i : idx) {
            if (directions[i] == 'R') {
                stk.push_back(i);
                continue;
            }

            while (!stk.empty() && healths[i] > 0) {
                int j = stk.back();

                if (healths[j] > healths[i]) {
                    healths[j]--;
                    healths[i] = 0;
                } else if (healths[j] < healths[i]) {
                    healths[i]--;
                    healths[j] = 0;
                    stk.pop_back();
                } else {
                    healths[i] = healths[j] = 0;
                    stk.pop_back();
                    break;
                }
            }
        }

        vector<int> ans;
        for (int h : healths) {
            if (h > 0) {
                ans.push_back(h);
            }
        }
        return ans;
    }
};
function survivedRobotsHealths(
    positions: number[],
    healths: number[],
    directions: string,
): number[] {
    const n = positions.length;
    const idx = Array.from({ length: n }, (_, i) => i).sort((a, b) => positions[a] - positions[b]);

    const stk: number[] = [];

    for (const i of idx) {
        if (directions[i] === 'R') {
            stk.push(i);
            continue;
        }

        while (stk.length && healths[i] > 0) {
            const j = stk[stk.length - 1];

            if (healths[j] > healths[i]) {
                healths[j]--;
                healths[i] = 0;
            } else if (healths[j] < healths[i]) {
                healths[i]--;
                healths[j] = 0;
                stk.pop();
            } else {
                healths[i] = healths[j] = 0;
                stk.pop();
                break;
            }
        }
    }

    return healths.filter(h => h > 0);
}
func survivedRobotsHealths(positions []int, healths []int, directions string) []int {
	n := len(positions)
	idx := make([]int, n)
	for i := range idx {
		idx[i] = i
	}

	sort.Slice(idx, func(i, j int) bool {
		return positions[idx[i]] < positions[idx[j]]
	})

	stk := []int{}

	for _, i := range idx {
		if directions[i] == 'R' {
			stk = append(stk, i)
			continue
		}

		for len(stk) > 0 && healths[i] > 0 {
			j := stk[len(stk)-1]

			if healths[j] > healths[i] {
				healths[j]--
				healths[i] = 0
			} else if healths[j] < healths[i] {
				healths[i]--
				healths[j] = 0
				stk = stk[:len(stk)-1]
			} else {
				healths[i], healths[j] = 0, 0
				stk = stk[:len(stk)-1]
				break
			}
		}
	}

	ans := []int{}
	for _, h := range healths {
		if h > 0 {
			ans = append(ans, h)
		}
	}
	return ans
}
impl Solution {
    pub fn survived_robots_healths(
        positions: Vec<i32>,
        mut healths: Vec<i32>,
        directions: String
    ) -> Vec<i32> {
        let n = positions.len();
        let mut idx: Vec<usize> = (0..n).collect();

        idx.sort_by_key(|&i| positions[i]);

        let dirs = directions.as_bytes();
        let mut stk: Vec<usize> = Vec::new();

        for &i in &idx {
            if dirs[i] == b'R' {
                stk.push(i);
                continue;
            }

            while let Some(&j) = stk.last() {
                if healths[i] == 0 {
                    break;
                }

                if healths[j] > healths[i] {
                    healths[j] -= 1;
                    healths[i] = 0;
                    break;
                } else if healths[j] < healths[i] {
                    healths[i] -= 1;
                    healths[j] = 0;
                    stk.pop();
                } else {
                    healths[i] = 0;
                    healths[j] = 0;
                    stk.pop();
                    break;
                }
            }
        }

        healths.into_iter().filter(|&h| h > 0).collect()
    }
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Sorting and Stack-based Collision Detection

Time Complexity: O(n log n) due to sorting the list of robots.
Space Complexity: O(n) because of the additional data structures used (stack and survivor list).

Two-Pointer Collision Simulation

Time Complexity: O(n log n) due to sorting the positions.
Space Complexity: O(n) due to extra data structures for handling collisions.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Sorting + Stack Collision DetectionO(n log n)O(n)General solution; clean collision modeling using a stack
Two-Pointer Collision SimulationO(n log n)O(n)When implementing a pointer-based simulation without an explicit stack

Frequently asked questions

Is Robot Collisions easy or hard?

Robot Collisions is rated Hard because it combines sorting, stack-based collision handling, and careful simulation logic. The challenge comes from correctly updating health values and handling repeated collisions while maintaining the final output order.

How to solve Robot Collisions in O(n)?

Pure O(n) is only possible if robot positions are already sorted. With sorted positions, you can scan from left to right and use a stack (or pointer tracking) to resolve collisions in linear time. Each robot participates in at most one push and one pop operation.

Robot Collisions Python or Java solution

Most implementations follow the same pattern: sort robot indices by position, iterate through them, and use a stack to manage right-moving robots. Python and Java solutions typically store indices in the stack and update the health array directly during collision resolution.

What is the best approach for Robot Collisions?

The sorting + stack simulation is the most reliable approach. First sort robots by position, then use a stack to track right-moving robots and resolve collisions when a left-moving robot appears. Each collision is processed in constant time, giving O(n log n) overall complexity due to sorting and O(n) space.

Is Robot Collisions asked at Google/Amazon/Meta?

Collision simulation and stack-based interaction problems frequently appear in interviews at companies like Amazon, Google, and Meta. Robot Collisions is conceptually similar to problems such as Asteroid Collision, which is a common interview question testing stacks and simulation logic.

What data structure is used in Robot Collisions?

A stack is the key data structure used to track robots moving to the right. When a left-moving robot appears, it repeatedly collides with robots from the stack until one survives or both are destroyed. Sorting is also required to process robots in positional order.

What is the time complexity of Robot Collisions?

The optimal solution runs in O(n log n) time because robots must be sorted by position before simulating collisions. After sorting, the stack-based collision processing runs in O(n) since each robot is pushed and popped at most once.

Comments

Now write it yourselfClose this page and solve Robot Collisions in the editor, without looking.
Practise Robot Collisions