Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@
* [Decoding](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/huffman/decoding.py)
* [Encoding](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/huffman/encoding.py)
* Intervals
* Car Pooling
* [Test Car Pooling](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/intervals/car_pooling/test_car_pooling.py)
* Count Days
* [Test Count Days Without Meetings](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/intervals/count_days/test_count_days_without_meetings.py)
* Full Bloom Flowers
Expand Down
97 changes: 97 additions & 0 deletions algorithms/intervals/car_pooling/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Car Pooling

You are given a car with a fixed number of seats, denoted by an integer capacity. The car only travels in one direction
— eastward — and does not make any U-turns.

You are also provided with an array, trips, where each element trips[i]= [numPassengersi, fromi, toi] represents a group of
numPassengersi that must be picked up at location fromi and dropped off at location toi . All locations are measured in
kilometers east of the starting point.

Your task is to determine whether it is possible to complete all the trips without exceeding the car’s capacity at any
point in time.

Return TRUE if all trips can be completed successfully, or FALSE otherwise.

## Constraints

- 1 <= `trips.length` <= 1000
- `trips[i].length` == 3
- 1 <= `numPassengers` <= 1000
- 0 <= fromi < toi <= 1000
- 1 <= `capacity` <= 10^5

## Examples

![Example 1](./images/examples/car_pooling_example_1.png)
![Example 2](./images/examples/car_pooling_example_2.png)
![Example 3](./images/examples/car_pooling_example_3.png)


## Solution

The core intuition behind this solution is to simulate the journey of the car using a timeline, tracking when passengers
get in and get out. This approach aligns with the merge intervals pattern, where we focus on events happening at specific
points in time, rather than handling each trip separately in isolation. The idea is to accumulate and monitor the number
of passengers in the car at any moment using a difference array (also known as a prefix sum technique).

In the context of this problem, each trip defines a passenger change over a specific interval — passengers are picked up
at from and dropped off at to. Instead of iterating over the entire interval (which is inefficient), we can track just
the start and end of the interval using a fixed-size timeline array.

This strategy is built on two key observations:

1. Each trip contributes a net passenger change at exactly two locations:
- Increase at the pickup location (from)
- Decrease at the drop-off location (to)

2. The car’s capacity must never be exceeded at any point on the journey, so we monitor the cumulative passenger count
as we move forward in time.

This strategy leverages the difference array pattern, which is a version of merge intervals. Rather than merging
overlapping intervals explicitly, it simulates all trips together via a timeline of passenger changes.

Let’s break down the steps:

1. A list timestamp of size 1001 (based on constraints) is created to track changes in passenger counts at each kilometer
point.
2. For each trip `[numPassengersi ,fromi, toi]` in trips:
- Add numPassengers at `timestamp[fromi]`
- Subtract numPassengers at `timestamp[toi]`

This marks the start and end of each passenger interval without iterating over the full range.

3. To simulate the trip and track capacity, initialize a variable used_capacity = 0.
4. Iterate through the timestamp list, adding the passenger changes at each point. If at any point used_capacity > capacity,
return FALSE immediately— the car is overloaded.
5. If the full timeline is processed without exceeding capacity, return TRUE, indicating that all trips can be accommodated.

Let’s look at the following illustration to get a better understanding of the solution:

![Solution 1](./images/solutions/car_pooling_solution_1.png)
![Solution 2](./images/solutions/car_pooling_solution_2.png)
![Solution 3](./images/solutions/car_pooling_solution_3.png)
![Solution 4](./images/solutions/car_pooling_solution_4.png)
![Solution 5](./images/solutions/car_pooling_solution_5.png)
![Solution 6](./images/solutions/car_pooling_solution_6.png)
![Solution 7](./images/solutions/car_pooling_solution_7.png)
![Solution 8](./images/solutions/car_pooling_solution_8.png)
![Solution 9](./images/solutions/car_pooling_solution_9.png)
![Solution 10](./images/solutions/car_pooling_solution_10.png)
![Solution 11](./images/solutions/car_pooling_solution_11.png)
![Solution 12](./images/solutions/car_pooling_solution_12.png)

### Time Complexity

The overall time complexity of the solution is O(n) because:

- The trips list is scanned once to record passenger changes at pickup and drop-off points.
- Each trip results in two constant-time operations: one increment and one decrement in the timeline array.
- The timestamp array (of fixed length 1001) is traversed once to simulate the journey and check capacity constraints.

As the length of timestamp is constant and independent of input size, it contributes O(1) time. So, the total operations
scale linearly with the number of trips.

### Space Complexity

The space complexity of the solution is O(1) because a fixed-size array timestamp of length 1001 is used regardless of
the input size.
60 changes: 60 additions & 0 deletions algorithms/intervals/car_pooling/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from typing import List, Tuple


def car_pooling(trips: List[List[int]], capacity: int) -> bool:
"""
Calculates and checks whether it is possible to pick up and drop off passengers on the given trips given the car's
capacity
Args:
trips(list): The trips that the car makes while collecting passengers on the route
capacity(int): capacity of the car
Returns:
bool: whether it is possible to collect and drop all passengers along the route
"""
# For every trip, create two entries, the start with the passenger count and end with the passenger count
events: List[Tuple[int, int]] = []

# Create the events
for trip in trips:
num, start, end = trip
# Mark the increase and decrease in passengers at pickup and drop-off points
events.append((start, num)) # pick up
events.append((end, -num)) # drop off

# sort by the location
# If locations are equal, the negative value (drop-off)
# will naturally come before the positive value (pick-up)
events.sort()

# This keeps track of the current vehicle's capacity, which will be used along the trip to check how many passengers
# have been carried so far
current_occupancy = 0

# process events chronologically
for event in events:
location, change = event
current_occupancy += change
if current_occupancy > capacity:
return False

return True


def car_pooling_bucket(trips: List[List[int]], capacity: int) -> bool:
# Initialize a timeline to track changes in passenger count at each km mark (0 to 1000)
timestamp = [0] * 1001

# Mark the increase and decrease in passengers at pickup and drop-off points
for trip in trips:
num_passengers, start, end = trip
timestamp[start] += num_passengers # Pick up passengers
timestamp[end] -= num_passengers # Drop off passengers

# Simulate the car's journey by applying the passenger changes
used_capacity = 0
for passenger_change in timestamp:
used_capacity += passenger_change # Update current passenger count
if used_capacity > capacity: # Check if capacity is exceeded
return False # Trip configuration is invalid

return True # All trips are valid within capacity
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions algorithms/intervals/car_pooling/test_car_pooling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import unittest
from typing import List
from parameterized import parameterized
from algorithms.intervals.car_pooling import car_pooling, car_pooling_bucket

CAR_POOLING_TEST_CASES = [
([[3, 2, 6], [1, 4, 7], [2, 5, 8]], 5, False),
([[2, 0, 4], [3, 2, 6], [1, 5, 8]], 4, False),
([[1, 0, 3], [2, 2, 5], [3, 4, 6]], 6, True),
([[2, 1, 5], [3, 3, 7]], 4, False),
([[2, 1, 5], [3, 3, 7]], 5, True),
([[3, 2, 6], [1, 4, 7], [2, 5, 8]], 5, False),
([[1, 0, 4], [2, 2, 6], [3, 5, 8]], 6, True),
([[50, 0, 50], [51, 1, 51]], 100, False),
([[25, 0, 4], [25, 2, 6], [25, 5, 8]], 50, True),
]


class CarPoolingTestCases(unittest.TestCase):
@parameterized.expand(CAR_POOLING_TEST_CASES)
def test_car_pooling(self, trips: List[List[int]], capacity: int, expected: bool):
actual = car_pooling(trips, capacity)
self.assertEqual(expected, actual)

@parameterized.expand(CAR_POOLING_TEST_CASES)
def test_car_pooling_bucket_sort(
self, trips: List[List[int]], capacity: int, expected: bool
):
actual = car_pooling_bucket(trips, capacity)
self.assertEqual(expected, actual)


if __name__ == "__main__":
unittest.main()
Loading