LeetCode Β· #853

Car Fleet Solution

Given n cars heading toward a target, determine how many car fleets will arrive.

01
Section One Β· Problem

Problem Statement

🏷️

Difficulty

Medium

πŸ”—

LeetCode

Problem #853

πŸ—οΈ

Pattern

Sort + Stack β€” arrival time comparison

There are n cars going to the same destination target miles away. Each car i starts at position[i] with speed speed[i]. A car can never pass another β€” if it catches up, they form a fleet and travel at the slower car's speed. Return the number of fleets arriving at the target.

Example
Input: target = 12, position = [10,8,0,5,3], speed = [2,4,1,1,3] Output: 3 // Car at 10 (ETA 1.0) and car at 8 (ETA 1.0) β†’ fleet // Car at 5 (ETA 7.0) and car at 3 (ETA 3.0) β†’ 3 catches 5, fleet at ETA 7.0 // Car at 0 (ETA 12.0) β†’ alone // 3 fleets total
Constraints
β€’ n == position.length == speed.length β€’ 1 ≀ n ≀ 10⁡ β€’ 0 < target ≀ 10⁢ β€’ All positions are unique
02
Section Two Β· Approach 1

Brute Force β€” Simulation

Simulate the cars advancing in tiny time steps, merging fleets when a car catches the one ahead. Too slow for large inputs and requires floating-point precision handling.

Problem: Simulation is complex and slow. The key insight: a car's arrival time is (target βˆ’ position) / speed. Sort by position and compare arrival times β€” if a behind car arrives sooner or equal, it joins the fleet ahead.
03
Section Three Β· Approach 2

Sort + Stack β€” O(n log n)

Sort cars by position (closest to target first). Process them in order. Each car's arrival time = (target βˆ’ position) / speed. If a car's ETA is ≀ the car ahead (on the stack), it merges into that fleet. Otherwise, it forms a new fleet.

πŸ’‘ Mental model: Imagine watching cars from the finish line. The car closest to you arrives first (or determines the fleet speed). A car behind it that would arrive sooner can't pass β€” it gets stuck behind and joins the same fleet. Only when a car behind has a later arrival time does it form a new, independent fleet.
Algorithm
  • Step 1: Pair (position, speed), sort by position descending (closest to target first).
  • Step 2: For each car, compute ETA = (target βˆ’ position) / speed.
  • Step 3: If ETA > stack top β†’ new fleet β†’ push ETA.
  • Step 4: If ETA ≀ stack top β†’ merges into fleet ahead β†’ skip (don't push).
  • Step 5: Stack size = number of fleets.
🎯 Key insight:
  • We only need to compare adjacent cars (sorted by position). A car behind that arrives sooner gets absorbed.
  • A car behind that arrives later cannot catch the fleet ahead β€” it starts a new fleet.
  • The stack naturally tracks fleet arrival times.
04
Section Four Β· Trace

Visual Walkthrough

Trace: target=12, position=[10,8,0,5,3], speed=[2,4,1,1,3]

Sort by position desc, compare ETAs
Sorted by position (desc): posβ†’speedβ†’ETA pos=10, spd=2 β†’ ETA = (12-10)/2 = 1.0 pos=8, spd=4 β†’ ETA = (12-8)/4 = 1.0 pos=5, spd=1 β†’ ETA = (12-5)/1 = 7.0 pos=3, spd=3 β†’ ETA = (12-3)/3 = 3.0 pos=0, spd=1 β†’ ETA = (12-0)/1 = 12.0 Process: ETA 1.0: stack empty β†’ push stack: [1.0] (fleet 1) ETA 1.0: 1.0 ≀ 1.0 β†’ merges stack: [1.0] ETA 7.0: 7.0 > 1.0 β†’ new fleet stack: [1.0, 7.0] (fleet 2) ETA 3.0: 3.0 ≀ 7.0 β†’ merges stack: [1.0, 7.0] ETA 12.0: 12.0 > 7.0 β†’ new fleet stack: [1.0, 7.0, 12.0] (fleet 3)
Answer: Stack size = 3 fleets.
05
Section Five Β· Implementation

Code β€” Java & Python

Java β€” Sort + Stack
import java.util.*; class Solution { public int carFleet(int target, int[] position, int[] speed) { int n = position.length; int[][] cars = new int[n][2]; for (int i = 0; i < n; i++) cars[i] = new int[]{position[i], speed[i]}; Arrays.sort(cars, (a, b) -> b[0] - a[0]); // sort by position desc Stack<Double> stack = new Stack<>(); for (int[] car : cars) { double eta = (double)(target - car[0]) / car[1]; if (stack.isEmpty() || eta > stack.peek()) stack.push(eta); // new fleet // else: merges into fleet ahead β€” don't push } return stack.size(); } }
Python β€” Sort + Stack
class Solution: def carFleet(self, target: int, position: list[int], speed: list[int]) -> int: cars = sorted(zip(position, speed), reverse=True) stack = [] for pos, spd in cars: eta = (target - pos) / spd if not stack or eta > stack[-1]: stack.append(eta) # new fleet return len(stack)
06
Section Six Β· Analysis

Complexity Analysis

ApproachTimeSpaceTrade-off
Sort + Stack ← optimal O(n log n) O(n) Sort dominates. Stack pass is O(n).
07
Section Seven Β· Edge Cases

Edge Cases & Pitfalls

CaseInputWhy It Matters
Single carn=1One car β†’ 1 fleet.
All same speedspd=[2,2,2]Nobody catches anyone β†’ n fleets (if sorted differently).
All mergeClosest car slowestEveryone catches up β†’ 1 fleet.
Same ETATwo cars with equal ETAThey meet exactly at target β†’ same fleet. Use ≀ not <.
⚠ Common Mistake: Sorting by position ascending instead of descending. We must process the car closest to the target first β€” it's the "blocker." Cars behind it can merge into it, but never pass. Processing from farthest-first would miss fleet merges.

← Back to Stack problems