Car Fleet
Table of Contents + −
Cars on a one-lane road cannot pass each other. A faster car behind a slower one just bunches up and matches its speed. The question asks how many separate groups reach the finish line. The trick is to stop thinking about speed and start thinking about arrival time. Once you do that, a stack solves it.
🎯 The Problem
You return how many separate groups of cars reach the target.
- The target is where the road ends.
- You get a list of car positions and a matching list of speeds.
- The road has one lane, so a car can never pass the car ahead.
- A faster car that catches the slower car in front slows down and they move together.
- A group of cars moving together is a fleet.
Let us use target 12, positions [10, 8, 0, 5, 3], and speeds [2, 4, 1, 1, 3]. For each car work out the time to reach the target. That is distance left divided by speed. The car at 10 needs 1. The car at 8 needs 1. The car at 0 needs 12. The car at 5 needs 7. The car at 3 needs 3.
Input: target = 12, position = [10, 8, 0, 5, 3], speed = [2, 4, 1, 1, 3]Output: 3
Explanation: the cars form 3 fleets that reach the target.Here is the road as a picture. The target is on the right, and cars sit at their positions.
🐢 Approach 1: Simulate Every Moment (Brute Force)
Move time forward in tiny steps and watch the cars bunch up.
The idea:
- Step time forward a little at a time.
- Update every car’s position at each step.
How it works:
- When a car catches the one ahead, glue them together.
- Keep going until all cars reach the target.
- Count the groups at the end.
Why it is weak:
- You do not know how small the time steps must be.
- Tiny steps mean huge numbers of updates.
- Big steps might miss the exact moment two cars meet.
- It is hard to get right and has no clean time bound.
Here is the direct arrival-time simulation:
def car_fleet(target, position, speed): cars = sorted(zip(position, speed), reverse=True) fleets = 0 slowest_time = 0
for pos, spd in cars: time = (target - pos) / spd if time > slowest_time: fleets += 1 slowest_time = time return fleets⚡ Approach 2: Sort and Use a Stack of Times (Best)
The idea in one line: forget moving the cars, just compare when each one would reach the target.
The idea:
- For each car compute its arrival time, which is
(target - position) / speed. - Sort cars by position, closest to the target first.
- A car can only be blocked by a car ahead, so the fleet ahead is already decided.
How it works:
- Keep a stack of fleet arrival times. The top is the fleet just ahead.
- If a car’s time is bigger than the fleet ahead, it arrives later, so it never catches up. Push it as a new fleet.
- If its time is smaller or equal, it catches up and joins. Do not push.
Why it is fast:
- One sort, then a single walk through the cars.
- The number of items on the stack at the end is the number of fleets.
Here is the dry run for our example. Cars are sorted by position, closest first. Watch the stack of fleet times grow.
Steps to Solve
- Pair each car with its position and speed.
- Sort the cars by position, from closest to the target down to farthest.
- Make an empty stack of fleet arrival times.
- For each car compute its arrival time, which is target minus position divided by speed.
- If that time is bigger than the time on top of the stack, push it as a new fleet. Otherwise it joins the fleet ahead.
- The number of items on the stack is the answer.
This Python version pairs position with speed, sorts by position from the front, and counts fleets.
def car_fleet(target, position, speed): # pair each car and sort by position, closest to target first cars = sorted(zip(position, speed), reverse=True) stack = [] # arrival times of fleets for pos, spd in cars: time = (target - pos) / spd # how long this car takes # if it would catch the fleet ahead, it joins (do not push) if not stack or time > stack[-1]: stack.append(time) # a new fleet return len(stack)
position = [10, 8, 0, 5, 3]speed = [2, 4, 1, 1, 3]target = 12print(car_fleet(target, position, speed))The output of the above code will be:
3Let us read the Python version line by line and see why each line is written this way.
The line cars = sorted(zip(position, speed), reverse=True) does two jobs. The zip glues each position to its speed, so they stay together. Then sorted(..., reverse=True) sorts the pairs from the largest position down to the smallest. Largest position means closest to the target. We process front cars first because a car can only be blocked by a car ahead of it. So cars becomes [(10,2), (8,4), (5,1), (3,3), (0,1)].
The line stack = [] holds the arrival times of the fleets we have found. The loop for pos, spd in cars reads each car from front to back. The line time = (target - pos) / spd is the arrival time. It is the distance left divided by the speed.
The check if not stack or time > stack[-1] is the heart of it. stack[-1] is the time of the fleet just ahead. If the stack is empty, this is the first car, so it must be a new fleet. If this car’s time is bigger than the fleet ahead, it arrives later, so it can never catch up. That makes it a new fleet, and stack.append(time) records it. If its time is smaller or equal, it would catch the fleet ahead and join it. In that case we do nothing, so it is not counted again. At the end return len(stack) gives the number of fleets.
⏱️ Time and Space Complexity
The sort is the heavy step, so the time is O(n log n), where n is the number of cars. After sorting we just walk through the cars once, which is O(n). The stack and the sorted list each hold up to n items, so the space is O(n). The simulation approach has no clean bound and is far worse in practice.
| Approach | Time Complexity | Space Complexity |
|---|---|---|
| Simulate every moment (brute force) | Very slow, no clean bound | O(n) |
| Sort and stack of times (best) | O(n log n) | O(n) |
Tip
The whole problem turns easy once you switch from speed to arrival time. A car ahead that arrives later blocks a faster car behind it. So the fleet’s arrival time is set by the slowest car in front.
🧩 Key Takeaways
- ✅ A fleet is a group of cars that reach the target together because they cannot pass.
- ✅ Stop thinking about speed. Compute each car’s arrival time instead.
- ✅ Sort cars by position from closest to the target down to farthest.
- ✅ A car that arrives later than the fleet ahead becomes a new fleet. Otherwise it joins.
- ✅ The number of items on the stack at the end is the number of fleets.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What is a fleet in this problem?
Why: Cars cannot pass, so a faster car bunches with the slower one ahead and they form a fleet.
- 2
What value do we compute for each car to solve this cleanly?
Why: Arrival time turns the moving problem into a simple comparison of when each car reaches the target.
- 3
In what order do we process the cars?
Why: A car can only be blocked by a car ahead, so we process from the front of the road backward.
- 4
When does a car start a new fleet?
Why: If a car arrives later than the fleet ahead, it never catches up, so it forms its own new fleet.