Cars travelling toward the same target merge into fleets when a faster car catches a slower one ahead. Sort by starting position, compute each car's arrival time, then use a monotonic stack of times to count how many distinct fleets reach the finish.
You have n cars on a one-lane road, each with a starting position and a speed. They all drive toward the same targetmile marker. A faster car that catches a slower one in front can't pass — they merge and travel together as a fleetat the slower car's speed. Return how many fleets arrive at the target.
Concrete example: target=12, position=[10,8,0,5,3], speed=[2,4,1,1,3].
Arrival times: car@10 → 1.0 hr, car@8 → 1.0 hr, car@5 → 7.0 hr, car@3 → 3.0 hr, car@0 → 12.0 hr. The car at 8 catches the car at 10 (same time → same fleet). The car at 3 can't catch the fleet at 5 (3.0 < 7.0 but it's behind and slower than the fleet). Three fleets arrive. Expected output: 3.
time = (target − pos) / spd. This is how many hours it would take if no blocking occurred.continue(don't push). Otherwise it outruns the fleet ahead and starts a new fleet — push its time.time <= stack[top], not <. When two cars have the exact same arrival time the rear car catches the front car right at the target — they count as one fleet. Using strict < would double-count that pair.The stack holds at most narrival times. In practice you don't even need the actual stack values — just the count and the time of the current top. Some solutions track only fleets and prevTime, reducing space to O(1) after sorting.
1function carFleet(target: number, position: number[], speed: number[]): number {2▶ const n = position.length;3 // Pair up and sort by starting position, closest to target first4▶ const cars = position5▶ .map((pos, i) => ({ pos, spd: speed[i] }))6▶ .sort((a, b) => b.pos - a.pos);78 // stack holds the arrival times of fleets (monotone increasing from front to back)9▶ const stack: number[] = [];1011 for (const { pos, spd } of cars) {12 const time = (target - pos) / spd;13 // If this car arrives no later than the fleet in front, it gets blocked and joins it14 if (stack.length > 0 && time <= stack[stack.length - 1]) continue;15 // Otherwise it outruns the fleet ahead and forms a new one16 stack.push(time);17 }1819 return stack.length;20}
function carFleet(target: number, position: number[], speed: number[]): number {
const n = position.length;
// Pair up and sort by starting position, closest to target first
const cars = position
.map((pos, i) => ({ pos, spd: speed[i] }))
.sort((a, b) => b.pos - a.pos);
// stack holds the arrival times of fleets (monotone increasing from front to back)
const stack: number[] = [];
for (const { pos, spd } of cars) {
const time = (target - pos) / spd;
// If this car arrives no later than the fleet in front, it gets blocked and joins it
if (stack.length > 0 && time <= stack[stack.length - 1]) continue;
// Otherwise it outruns the fleet ahead and forms a new one
stack.push(time);
}
return stack.length;
}pos means the first car we process is the one closest to the target — the natural order for determining who blocks whom.(target - pos) / spd gives the unconstrained arrival time. Crucially, we compute this for the original speed; blocking is handled implicitly by the stack comparison, not by adjusting speeds.continue without pushing. Otherwise it travels faster overall and starts a new fleet; push its time.stack.length is the answer.prevTime variable and a fleets counter; update them in the same single pass after sorting.(time, count)onto the stack; increment the top's count when a car joins instead of skipping it.function carFleet(target: number, position: number[], speed: number[]): number {
const n = position.length;
// Pair up and sort by starting position, closest to target first
const cars = position
.map((pos, i) => ({ pos, spd: speed[i] }))
.sort((a, b) => b.pos - a.pos);
// stack holds the arrival times of fleets (monotone increasing from front to back)
const stack: number[] = [];
for (const { pos, spd } of cars) {
const time = (target - pos) / spd;
// If this car arrives no later than the fleet in front, it gets blocked and joins it
if (stack.length > 0 && time <= stack[stack.length - 1]) continue;
// Otherwise it outruns the fleet ahead and forms a new one
stack.push(time);
}
return stack.length;
}Sort cars by position closest-to-target first and compute each arrival time. A car starts a new fleet only if its arrival time is strictly greater than the arrival time of every car ahead of it — so for each car, scan all the cars in front to check.
function carFleet(target: number, position: number[], speed: number[]): number {
// Sort by position descending (closest to target first)
const order = position
.map((pos, i) => ({ pos, time: (target - pos) / speed[i] }))
.sort((a, b) => b.pos - a.pos);
let fleets = 0;
for (let i = 0; i < order.length; i++) {
// A car leads its own fleet unless some car ahead arrives at the same time or later
let blocked = false;
for (let j = 0; j < i; j++) {
if (order[j].time >= order[i].time) { blocked = true; break; }
}
if (!blocked) fleets++;
}
return fleets;
}| cars merging when a faster one catches a slower one | sort + monotonic stack of arrival times |
| "how many groups reach the finish" | time-to-target comparison (blocked ⇒ join) |
| one-lane road, no passing | rear car time ≤ front fleet time ⇒ merge |
| count distinct fleets / groups after merging | stack.length after single pass |
function carFleet(target: number, position: number[], speed: number[]): number {
const cars = position
.map((pos, i) => ({ pos, spd: speed[i] }))
.sort((a, b) => b.pos - a.pos);
const stack: number[] = [];
for (const { pos, spd } of cars) {
const time = (target - pos) / spd;
if (stack.length > 0 && time <= stack[stack.length - 1]) continue;
stack.push(time);
}
return stack.length;
}target=12, position=[10,8,0,5,3], speed=[2,4,1,1,3]. How many fleets reach the target?[2.0, 5.0, 3.0]. What does the stack look like after processing all three cars?