Skip to content

Commit a86a9de

Browse files
committed
solve Car Pooling
1 parent 620738b commit a86a9de

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

problems/car_pooling.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
from collections import defaultdict
2+
from typing import List
3+
4+
5+
class Solution:
6+
# Since the max drop location can be 1000, we can store number of people in the
7+
# car at every location in a hash map. It will take O(1) space.
8+
# We iterate over every element of trips, and update our hash map.
9+
#
10+
# Time: O(1)
11+
# Space: O(1)
12+
# Since the number of trips is bounded.
13+
#
14+
# Further optimizations:
15+
# As we will see in the official solution, we could keep only the changes (the
16+
# delta) in the hash map.
17+
def carPooling(self, trips: List[List[int]], capacity: int) -> bool:
18+
counts = defaultdict(int)
19+
max_count = 0
20+
for trip in trips:
21+
for loc in range(trip[1], trip[2]):
22+
counts[loc] += trip[0]
23+
max_count = max(max_count, counts[loc])
24+
if max_count > capacity:
25+
return False
26+
return True
27+
28+
29+
class OfficialSolution:
30+
"""
31+
== Overview ==
32+
It is one of the classical problems related to intervals, and we have some similar
33+
problems such as Meeting Rooms II at LeetCode. Below, two approaches are introduced:
34+
the simple Time Stamp approach, and the Bucket Sort approach.
35+
"""
36+
37+
def carPoolingApproach1(self, trips: List[List[int]], capacity: int) -> bool:
38+
"""
39+
== Approach 1: Time Stamp ==
40+
== Intuition ==
41+
A simple idea is to go through from the start to end, and check if the actual
42+
capacity exceeds `capacity`. To know the actual capacity, we just need the number of
43+
passengers changed at each timestamp.
44+
We can save the number of passengers changed at each time, sort it by timestamp, and
45+
finally iterate it to check the actual capacity.
46+
47+
== Algorithm ==
48+
We will initialize a list to store the number of passengers changed and the
49+
corresponding timestamp and then sort it.
50+
Finally, we just need to iterate from the start timestamp to the end timestamp, and
51+
check if the actual capacity meets the condition.
52+
53+
== Complexity Analysis ==
54+
Assume N is the length of the trips.
55+
Time Complexity: O(NlgN) since we need to iterate over trips and sort our timestamp.
56+
Iterating costs O(N), and sorting costs O(NlgN), and adding together we have
57+
O(N) + O(NlgN) = O(NlgN).
58+
Space Complexity: O(N) to store timestamp.
59+
"""
60+
timestamp = []
61+
for trip in trips:
62+
timestamp.append([trip[1], trip[0]])
63+
timestamp.append([trip[2], -trip[0]])
64+
65+
timestamp.sort()
66+
67+
used_capacity = 0
68+
for time, passenger_change in timestamp:
69+
used_capacity += passenger_change
70+
if used_capacity > capacity:
71+
return False
72+
73+
return True
74+
75+
def carPoolingApproach2(self, trips: List[List[int]], capacity: int) -> bool:
76+
"""
77+
== Approach 2: Bucket Sort ==
78+
== Intuition ==
79+
Note that in the problem there is a interesting constraint:
80+
0 <= trips[i][1] < trips[i][2] <= 1000
81+
What pops into the mind is Bucket Sort, which is a sorting algorithm in O(N)
82+
time but requires prior knowledge for the range of the data.
83+
We can use it instead of the normal sorting in this method.
84+
What we do is initial 1001 buckets, and put the number of passengers changed in
85+
corresponding buckets, and collect the buckets one by one.
86+
87+
== Algorithm ==
88+
We will initialize 1001 buckets, iterate `trips`, and save the number of
89+
passengers changed at i mile in the i-th bucket.
90+
91+
== Complexity Analysis ==
92+
Assume N is the length of the trip.
93+
Time Complexity: O(max(N, 10001)), since we need to iterate over trips and then
94+
iterate over 1001 buckets.
95+
Space Complexity: O(1001) = O(1) since we have 1001 buckets.
96+
"""
97+
timestamp = [0] * 1001
98+
for trip in trips:
99+
timestamp[trip[1]] += trip[0]
100+
timestamp[trip[2]] -= trip[0]
101+
102+
used_capacity = 0
103+
for passenger_change in timestamp:
104+
used_capacity += passenger_change
105+
if used_capacity > capacity:
106+
return False
107+
108+
return True

tests/test_car_pooling.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import unittest
2+
3+
from car_pooling import Solution
4+
5+
6+
class TestCarPooling(unittest.TestCase):
7+
def test_example_1(self):
8+
assert Solution().carPooling(trips=[[2, 1, 5], [3, 3, 7]], capacity=4) is False
9+
10+
def test_example_2(self):
11+
assert Solution().carPooling(trips=[[2, 1, 5], [3, 3, 7]], capacity=5) is True
12+
13+
def test_example_3(self):
14+
assert Solution().carPooling(trips=[[2, 1, 5], [3, 5, 7]], capacity=3) is True
15+
16+
def test_example_4(self):
17+
assert (
18+
Solution().carPooling(trips=[[3, 2, 7], [3, 7, 9], [8, 3, 9]], capacity=11)
19+
is True
20+
)

0 commit comments

Comments
 (0)