Problem
There are n
cars going to the same destination along a one-lane road. The destination is target
miles away.
You are given two integer array position
and speed
, both of length n
, where position[i]
is the position of the ith
car and speed[i]
is the speed of the ith
car (in miles per hour).
A car can never pass another car ahead of it, but it can catch up to it and drive bumper to bumper at the same speed. The faster car will slow down to match the slower car’s speed. The distance between these two cars is ignored (i.e., they are assumed to have the same position).
A car fleet is some non-empty set of cars driving at the same position and same speed. Note that a single car is also a car fleet.
If a car catches up to a car fleet right at the destination point, it will still be considered as one car fleet.
Return the number of car fleets that will arrive at the destination.
Examples
Example 1:
Input: target = 12, position = [10,8,0,5,3], speed = [2,4,1,1,3]
Output: 3
Explanation:
The cars starting at 10 (speed 2) and 8 (speed 4) become a fleet, meeting each other at 12.
The car starting at 0 does not catch up to any other car, so it is a fleet by itself.
The cars starting at 5 (speed 1) and 3 (speed 3) become a fleet, meeting each other at 6. The fleet moves at speed 1 until it reaches target.
Note that no other cars meet these fleets before the destination, so the answer is 3.
Example 2:
Input: target = 10, position = [3], speed = [3]
Output: 1
Explanation: There is only one car, hence there is only one fleet.
Example 3:
Input: target = 100, position = [0,2,4], speed = [4,2,1]
Output: 1
Explanation:
The cars starting at 0 (speed 4) and 2 (speed 2) become a fleet, meeting each other at 4. The fleet moves at speed 2.
Then, the fleet (speed 2) and the car starting at 4 (speed 1) become one fleet, meeting each other at 6. The fleet moves at speed 1 until it reaches target.
Solution
Method 1 - Using Kinematics, stack and sorting
As illustrated in the example, Vehicle 1 is closest to the target and will lead a fleet since no vehicle behind it can overtake it. Vehicle 2, starting farther away but moving faster, would ideally reach the target first if Vehicle 1 wasn’t ahead. However, Vehicle 2 will join the fleet led by Vehicle 1 upon catching up. Vehicle 3 arrives later (at t2
time) than the fleet in front and thus forms its own fleet.
We can take following steps:
- Sort the vehicles by their
(position, speed)
pairs. - The first vehicle will form its own fleet. From the second vehicle onward, compare each vehicle’s ideal arrival time with the top of the stack, representing the latest arrival time of the current fleet.
- If a vehicle arrives earlier, it joins the existing fleet.
- Otherwise, it starts a new fleet, and its arrival time is added to the stack.
- The stack then contains the distinct arrival times, representing the number of fleets.
Code
Java
class Solution {
public int carFleet(int target, int[] position, int[] speed) {
int n = position.length;
Car[] cars = new Car[n];
for (int i = 0; i < n; i++) {
cars[i] = new Car(position[i], (double) (target - position[i]) / speed[i]);
}
Arrays.sort(cars, (a, b) -> Double.compare(b.position, a.position));
Stack<Double> stack = new Stack<>();
for (Car car : cars) {
if (stack.isEmpty() || car.time > stack.peek()) {
stack.push(car.time);
}
}
return stack.size();
}
class Car {
int position;
double time;
Car(int position, double time) {
this.position = position;
this.time = time;
}
}
}
Python
class Solution:
def carFleet(self, target: int, position: List[int], speed: List[int]) -> int:
stack = []
cars = sorted(zip(position, speed), reverse=True)
for pos, vel in cars:
time = (target - pos) / vel
if not stack or time > stack[-1]:
stack.append(time)
return len(stack)
Method 2 - Using Sorting
Here is the approach:
- Calculate Arrival Times: For each car, calculate its time to reach the target using the formula
(target - pos[i]) / speed[i]
. - Create an Array of Tuples: Store each car’s position and calculated arrival time in an array of tuples.
- Sort the Cars by Position: Sort the array of tuples based on position in ascending order to process cars from farthest to closest.
- Track Fleets Using Arrival Time:
- Initialize a variable
cur
to keep track of the current fleet’s arrival time. - Traverse the sorted array from the end:
- If a car’s arrival time is greater than the
cur
(current fleet’s time), it starts a new fleet. - Otherwise, it joins the current fleet.
- If a car’s arrival time is greater than the
- Initialize a variable
- Count Fleets: The number of times a new fleet is initiated during the traversal is the number of car fleets.
Code
Java
class Solution {
public int carFleet(int target, int[] pos, int[] speed) {
int n = pos.length;
double[][] arrivalTimes = new double[n][2];
// Calculate arrival times
for (int i = 0; i < n; i++) {
arrivalTimes[i] = new double[] {pos[i], (double)(target - pos[i]) / speed[i]};
}
// Sort the cars by their positions
Arrays.sort(arrivalTimes, (a, b) -> Double.compare(a[0], b[0]));
double cur = 0;
int ans = 0;
// Traverse the sorted array from the farthest car
for (int i = n - 1; i >= 0; i--) {
if (arrivalTimes[i][1] > cur) {
cur = arrivalTimes[i][1];
ans++;
}
}
return ans;
}
}
Python
class Solution:
def carFleet(self, target: int, position: List[int], speed: List[int]) -> int:
n = len(position)
arrival_times = [(position[i], (target - position[i]) / speed[i]) for i in range(n)]
# Sort the array by positions
arrival_times.sort(key=lambda x: x[0])
cur = 0.0
ans = 0
# Traverse the sorted list from the farthest car
for pos, time in reversed(arrival_times):
if time > cur:
cur = time
ans += 1
return ans
Complexity
- ⏰ Time complexity:
O(n log n)
due to sorting the array. - 🧺 Space complexity:
O(n)
for storing arrival times and positions of cars.
Method 3 - Using Treemap
Here is the approach:
- Calculate Arrival Times: Compute the time for each car to reach the target using the formula
(target - pos[i]) / speed[i]
. - Store in Map: Use a
TreeMap
to store the positions as keys and arrival times as values. The map is sorted in reverse order of positions automatically. - Traverse Map:
- Initialize a variable
cur
to track the current fleet’s arrival time. - Iterate through the values (arrival times) in the map:
- If a car’s arrival time is greater than
cur
, initiate a new fleet. - Update
cur
to the current car’s arrival time.
- If a car’s arrival time is greater than
- Initialize a variable
- Count Fleets: Count the number of times a new fleet is initiated during the iteration.
Code
Java
class Solution {
public int carFleet(int target, int[] pos, int[] speed) {
Map<Integer, Double> map = new TreeMap<>(Collections.reverseOrder());
// Calculate arrival times and store in TreeMap
for (int i = 0; i < pos.length; i++) {
map.put(pos[i], (double)(target - pos[i]) / speed[i]);
}
int res = 0;
double cur = 0;
// Iterate over the values in the TreeMap
for (double time : map.values()) {
if (time > cur) {
cur = time;
res++;
}
}
return res;
}
}
Python
class Solution:
def carFleet(self, target: int, position: List[int], speed: List[int]) -> int:
# Calculate arrival times and store in a sorted dictionary
arrival_times = {pos: (target - pos) / speed for pos, speed in zip(position, speed)}
sorted_arrival_times = collections.OrderedDict(sorted(arrival_times.items(), key=lambda item: item[0], reverse=True))
res = 0
cur = 0.0
# Iterate over the values in the sorted dictionary
for time in sorted_arrival_times.values():
if time > cur:
cur = time
res += 1
return res
Complexity
- ⏰ Time complexity:
O(n log n)
due to sorting in theTreeMap
. - 🧺 Space complexity:
O(n)
for storing arrival times in the map.