There is a car with capacity empty seats. The vehicle only drives east (i.e., it cannot turn around and drive west).
You are given the integer capacity and a integer array trips where trips[i] = [numPassengers[i], from[i], to[i]] indicates that the ith trip has numPassengers[i] passengers and the locations to pick them up and drop them off are from[i] and to[i] respectively. The locations are given as the number of kilometers due east from the car's initial location.
Return true if it is possible to pick up and drop off all passengers for all the given trips, or false otherwise.
Please upgrade to NeetCode Pro to view company tags.
Prerequisites
Before attempting this problem, you should be comfortable with:
Sorting - Sorting events or intervals by start/end points
Min-Heap (Priority Queue) - Efficiently tracking and removing minimum elements
Line Sweep / Difference Array - Processing interval changes as discrete events
1. Brute Force
Intuition
At each pickup location, we need to know how many passengers are currently in the car. We can sort trips by their start location and for each trip, check all previous trips that have not yet dropped off their passengers. If the total exceeds capacity at any point, carpooling is not possible.
Algorithm
Sort all trips by their pickup location (start time).
For each trip at index i:
Start with the number of passengers from the current trip.
Check all previous trips (j < i) and add their passengers if their drop-off location is after the current pickup location.
If the total passengers exceed capacity, return false.
If all trips pass the capacity check, return true.
Space complexity: O(1) or O(n) depending on the sorting algorithm.
2. Min-Heap
Intuition
When we process trips in order of pickup time, we only care about trips whose passengers are still in the car. A min-heap ordered by drop-off time lets us efficiently remove all trips whose passengers have already been dropped off before the current pickup. This way, we maintain a running count of current passengers.
Algorithm
Sort trips by their pickup location.
Use a min-heap to track active trips, ordered by their drop-off location.
For each trip:
Pop all trips from the heap whose drop-off location is at or before the current pickup, subtracting their passengers from the count.
Add the current trip's passengers to the count.
If the count exceeds capacity, return false.
Push the current trip (drop-off time, passenger count) onto the heap.
Return true if all trips are processed without exceeding capacity.
Think of each trip as two events: passengers getting on at the start and passengers getting off at the end. By treating pickups as positive changes and drop-offs as negative changes, we can process all events in sorted order. At any point, if the cumulative passenger count exceeds capacity, the answer is false.
Algorithm
Create a list of events: (location, +passengers) for pickups and (location, -passengers) for drop-offs.
Sort events by location. If two events have the same location, process drop-offs (negative) before pickups to handle edge cases correctly.
Iterate through events, maintaining a running passenger count.
class Solution {funcarPooling(trips: Array<IntArray>, capacity: Int): Boolean {val points = mutableListOf<IntArray>()for(trip in trips){val(passengers, start, end)= trip
points.add(intArrayOf(start, passengers))
points.add(intArrayOf(end,-passengers))}
points.sortWith{ a, b ->if(a[0]== b[0]) a[1]- b[1]else a[0]- b[0]}var curPass =0for(point in points){
curPass += point[1]if(curPass > capacity){returnfalse}}returntrue}}
classSolution{funccarPooling(_ trips:[[Int]],_ capacity:Int)->Bool{var points =[(Int,Int)]()for trip in trips {let passengers = trip[0], start = trip[1], end = trip[2]
points.append((start, passengers))
points.append((end,-passengers))}
points.sort { a, b inif a.0== b.0{return a.1< b.1}return a.0< b.0}var curPass =0for point in points {
curPass += point.1if curPass > capacity {returnfalse}}returntrue}}
Time & Space Complexity
Time complexity: O(nlogn)
Space complexity: O(n)
4. Line Sweep - II
Intuition
Instead of sorting events, we can use an array where each index represents a location on the route. We record passenger changes at each location: add passengers at pickup points and subtract at drop-off points. A single pass through this array gives us the passenger count at each location.
Algorithm
Find the range of locations (leftmost pickup to rightmost drop-off).
Create an array of size (range + 1) initialized to zero.
For each trip, add passengers at the pickup index and subtract at the drop-off index.
Iterate through the array, accumulating the passenger count.
If the count ever exceeds capacity, return false. Otherwise, return true.
classSolution:defcarPooling(self, trips: List[List[int]], capacity:int)->bool:
L, R =float("inf"),float("-inf")for _, start, end in trips:
L =min(L, start)
R =max(R, end)
N = R - L +1
passChange =[0]*(N +1)for passengers, start, end in trips:
passChange[start - L]+= passengers
passChange[end - L]-= passengers
curPass =0for change in passChange:
curPass += change
if curPass > capacity:returnFalsereturnTrue
publicclassSolution{publicboolCarPooling(int[][] trips,int capacity){int L =int.MaxValue, R =int.MinValue;foreach(var trip in trips){int start = trip[1], end = trip[2];
L = Math.Min(L, start);
R = Math.Max(R, end);}int N = R - L +1;int[] passChange =newint[N +1];foreach(var trip in trips){int passengers = trip[0];int start = trip[1];int end = trip[2];
passChange[start - L]+= passengers;
passChange[end - L]-= passengers;}int curPass =0;foreach(int change in passChange){
curPass += change;if(curPass > capacity)returnfalse;}returntrue;}}
funccarPooling(trips [][]int, capacity int)bool{
L, R := math.MaxInt32, math.MinInt32
for_, trip :=range trips {
start, end := trip[1], trip[2]if start < L {
L = start
}if end > R {
R = end
}}
N := R - L +1
passChange :=make([]int, N+1)for_, trip :=range trips {
passengers, start, end := trip[0], trip[1], trip[2]
passChange[start-L]+= passengers
passChange[end-L]-= passengers
}
curPass :=0for_, change :=range passChange {
curPass += change
if curPass > capacity {returnfalse}}returntrue}
class Solution {funcarPooling(trips: Array<IntArray>, capacity: Int): Boolean {var L = Int.MAX_VALUE
var R = Int.MIN_VALUE
for(trip in trips){val start = trip[1]val end = trip[2]
L =minOf(L, start)
R =maxOf(R, end)}val N = R - L +1val passChange =IntArray(N +1)for(trip in trips){val passengers = trip[0]val start = trip[1]val end = trip[2]
passChange[start - L]+= passengers
passChange[end - L]-= passengers
}var curPass =0for(change in passChange){
curPass += change
if(curPass > capacity){returnfalse}}returntrue}}
classSolution{funccarPooling(_ trips:[[Int]],_ capacity:Int)->Bool{varL=Int.max
varR=Int.min
for trip in trips {let start = trip[1], end = trip[2]L=min(L, start)R=max(R, end)}letN=R-L+1var passChange =[Int](repeating:0, count:N+1)for trip in trips {let passengers = trip[0], start = trip[1], end = trip[2]
passChange[start -L]+= passengers
passChange[end -L]-= passengers
}var curPass =0for change in passChange {
curPass += change
if curPass > capacity {returnfalse}}returntrue}}
Time & Space Complexity
Time complexity: O(n+N)
Space complexity: O(N)
Where n is the size of the array trips and N is the difference between the rightmost location and the leftmost location.
Common Pitfalls
Not Processing Drop-offs Before Pickups at Same Location
When a passenger is dropped off and another is picked up at the same location, the drop-off must happen first. Failing to sort events so that drop-offs (negative values) come before pickups at the same location causes false capacity violations.
# Wrong: no tiebreaker for same location
points.sort(key=lambda x: x[0])# Correct: drop-offs (negative) before pickups at same location
points.sort(key=lambda x:(x[0], x[1]))
Checking Passengers Still in Car at Drop-off Location
Passengers are dropped off at the end location and are not in the car during that location. A common mistake is including passengers who should have already exited, leading to overcounting.
# Wrong: includes passengers still at drop-offif trips[j][2]>= trips[i][1]:# Correct: only count if drop-off is strictly after pickupif trips[j][2]> trips[i][1]:
Off-by-One Error in Difference Array Index
When using a difference array, failing to account for the offset between actual locations and array indices causes incorrect passenger counts. This is especially problematic when locations do not start at zero.