Skip to content

Commit

Permalink
Car Fleet
Browse files Browse the repository at this point in the history
  • Loading branch information
dksifoua committed Jul 20, 2024
1 parent ff97c21 commit 931d8ed
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@
| 0238 | Medium | Product of Array Except Self | Array | [solution](./docs/0238-Product-Of-Array-Except-Self.md) |
| 0242 | Easy | Valid Anagram | String, HashTable | [solution](./docs/0242-Valid-Anagram.md) |
| 0347 | Medium | Top K Frequent Elements | Array, HashMap, Bucket Sort | [Solution](./docs/0347-Top-K-Frequent-Elements.md) |
| 0739 | Medium | Daily Temperatures | Array, Stack, Monotonic Stack | [solution](./docs/0139-Daily-Temperatures.md) |
| 0739 | Medium | Daily Temperatures | Array, Stack, Monotonic Stack | [solution](./docs/0139-Daily-Temperatures.md) |
| 0853 | Medium | Car Fleet | Array, Stack, Sorting, Monotonic Stack | [solution](./docs/0853-Car-Fleet.md) |
39 changes: 39 additions & 0 deletions docs/0853-Car-Fleet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# [Car Fleet](https://leetcode.com/problems/car-fleet/description/)

## Intuition

The problem is essentially about determining how many distinct groups (“fleets”) of cars will arrive at a target
destination, given that no car can overtake another but can form groups with any car it catches up to. The critical
insight here is to understand that cars closer to the destination at the start can only form a fleet with cars behind
them if those cars do not catch up by the target. Thus, sorting cars by their starting positions in descending order
allows us to simulate their journey and determine how many separate groups form by the time they reach the target.

## Approach

1. **Structuring the Data:** Use a record `PositionSpeed` to store each car’s starting position and speed. This helps in
organizing the data and simplifies operations on it.
2. **Sorting:** Sort the cars based on their starting positions in descending order. This way, we process cars that are
further from the destination first and keep adding cars to a fleet until a car cannot catch up, thus forming a distinct
fleet.
3. **Calculating Arrival Times:** For each car, calculate the time it would take to reach the target from its starting
position at its given speed. This is given by `(target - position) / speed`.
4. **Using a Stack to Form Fleets:**
- Utilize a stack to track the leading arrival times of each fleet. If a car’s calculated arrival time is greater
than the time on the stack (i.e., it takes longer to reach the destination than the car at the top of the stack), it
starts a new fleet, and its time gets pushed onto the stack.
- If a car can catch up (i.e., its arrival time is less than or equal to the time on the top of the stack), it joins
an existing fleet and does not change the stack.
5. **Determining the Number of Fleets:** The number of distinct arrival times in the stack at the end of the iteration
gives the number of fleets.

## Complexity

- ** Time Complexity: `O(NlogN)`**. The dominant factor here is the sorting step, which is `O(NlogN)`, where `N` is the
number of cars.
- **Space Complexity: `O(N)`** since we need space proportional to the number of cars for storing the `PositionSpeed`
records, the sorted list, and the stack that potentially can hold as many elements as there are cars in the worst-case
scenario.

## Code

- [Java](../src/main/java/io/dksifoua/leetcode/carfleet/Solution.java)
28 changes: 28 additions & 0 deletions src/main/java/io/dksifoua/leetcode/carfleet/Solution.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.dksifoua.leetcode.carfleet;

import java.util.*;

public class Solution {

private record PositionSpeed(int position, int speed) {};

public int carFleet(int target, int[] position, int[] speed) {
List<PositionSpeed> positionSpeeds = new ArrayList<>() {{
for (int i = 0; i < position.length; i++) {
add(new PositionSpeed(position[i], speed[i]));
}
}};
positionSpeeds.sort(Comparator.comparingInt(PositionSpeed::position).reversed());

Stack<Float> fleetHeads = new Stack<>();
for (PositionSpeed positionSpeed: positionSpeeds) {
float time = (float) (target - positionSpeed.position()) / positionSpeed.speed();
if (fleetHeads.isEmpty() || time > fleetHeads.peek()) {
fleetHeads.push(time);
}
}
System.out.println(fleetHeads);

return fleetHeads.size();
}
}
29 changes: 29 additions & 0 deletions src/test/java/io/dksifoua/leetcode/carfleet/SolutionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.dksifoua.leetcode.carfleet;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class SolutionTest {

public final Solution solution = new Solution();

@Test
void test1() {
Assertions.assertEquals(3, solution.carFleet(12, new int[] { 10, 8, 0, 5, 3 }, new int[] { 2, 4, 1, 1, 3 }));
}

@Test
void test2() {
Assertions.assertEquals(1, solution.carFleet(10, new int[] { 3 }, new int[] { 3 }));
}

@Test
void test3() {
Assertions.assertEquals(1, solution.carFleet(100, new int[] { 0, 2, 4 }, new int[] { 4, 2, 1 }));
}

@Test
void test4() {
Assertions.assertEquals(2, solution.carFleet(10, new int[] { 6, 8 }, new int[] { 3, 2 }));
}
}

0 comments on commit 931d8ed

Please sign in to comment.