Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Move from brute-force thinking to an efficient approach using hash map strategy.
A ride sharing system manages ride requests from riders and availability from drivers. Riders request rides, and drivers become available over time. The system should match riders and drivers in the order they arrive.
Implement the RideSharingSystem class:
RideSharingSystem() Initializes the system.void addRider(int riderId) Adds a new rider with the given riderId.void addDriver(int driverId) Adds a new driver with the given driverId.int[] matchDriverWithRider() Matches the earliest available driver with the earliest waiting rider and removes both of them from the system. Returns an integer array of size 2 where result = [driverId, riderId] if a match is made. If no match is available, returns [-1, -1].void cancelRider(int riderId) Cancels the ride request of the rider with the given riderId if the rider exists and has not yet been matched.Example 1:
Input:
["RideSharingSystem", "addRider", "addDriver", "addRider", "matchDriverWithRider", "addDriver", "cancelRider", "matchDriverWithRider", "matchDriverWithRider"]
[[], [3], [2], [1], [], [5], [3], [], []]
Output:
[null, null, null, null, [2, 3], null, null, [5, 1], [-1, -1]]
Explanation
RideSharingSystem rideSharingSystem = new RideSharingSystem(); // Initializes the systemExample 2:
Input:
["RideSharingSystem", "addRider", "addDriver", "addDriver", "matchDriverWithRider", "addRider", "cancelRider", "matchDriverWithRider"]
[[], [8], [8], [6], [], [2], [2], []]
Output:
[null, null, null, null, [8, 8], null, null, [-1, -1]]
Explanation
RideSharingSystem rideSharingSystem = new RideSharingSystem(); // Initializes the systemConstraints:
1 <= riderId, driverId <= 1000riderId is unique among riders and is added at most once.driverId is unique among drivers and is added at most once.addRider, addDriver, matchDriverWithRider, and cancelRider.Problem summary: A ride sharing system manages ride requests from riders and availability from drivers. Riders request rides, and drivers become available over time. The system should match riders and drivers in the order they arrive. Implement the RideSharingSystem class: RideSharingSystem() Initializes the system. void addRider(int riderId) Adds a new rider with the given riderId. void addDriver(int driverId) Adds a new driver with the given driverId. int[] matchDriverWithRider() Matches the earliest available driver with the earliest waiting rider and removes both of them from the system. Returns an integer array of size 2 where result = [driverId, riderId] if a match is made. If no match is available, returns [-1, -1]. void cancelRider(int riderId) Cancels the ride request of the rider with the given riderId if the rider exists and has not yet been matched.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Design
["RideSharingSystem","addRider","addDriver","addRider","matchDriverWithRider","addDriver","cancelRider","matchDriverWithRider","matchDriverWithRider"] [[],[3],[2],[1],[],[5],[3],[],[]]
["RideSharingSystem","addRider","addDriver","addDriver","matchDriverWithRider","addRider","cancelRider","matchDriverWithRider"] [[],[8],[8],[6],[],[2],[2],[]]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3829: Design Ride Sharing System
class RideSharingSystem {
private int t;
private TreeSet<int[]> riders;
private TreeSet<int[]> drivers;
private Map<Integer, Integer> d;
public RideSharingSystem() {
this.t = 0;
this.riders = new TreeSet<>(
(a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1]));
this.drivers = new TreeSet<>(
(a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1]));
this.d = new HashMap<>();
}
public void addRider(int riderId) {
d.put(riderId, t);
riders.add(new int[] {t, riderId});
t++;
}
public void addDriver(int driverId) {
drivers.add(new int[] {t, driverId});
t++;
}
public int[] matchDriverWithRider() {
if (riders.isEmpty() || drivers.isEmpty()) {
return new int[] {-1, -1};
}
int driverId = drivers.pollFirst()[1];
int riderId = riders.pollFirst()[1];
return new int[] {driverId, riderId};
}
public void cancelRider(int riderId) {
Integer time = d.get(riderId);
if (time != null) {
riders.remove(new int[] {time, riderId});
}
}
}
/**
* Your RideSharingSystem object will be instantiated and called as such:
* RideSharingSystem obj = new RideSharingSystem();
* obj.addRider(riderId);
* obj.addDriver(driverId);
* int[] param_3 = obj.matchDriverWithRider();
* obj.cancelRider(riderId);
*/
// Accepted solution for LeetCode #3829: Design Ride Sharing System
type RideSharingSystem struct {
t int
riders *redblacktree.Tree[int, int]
drivers *redblacktree.Tree[int, int]
d map[int]int
}
func Constructor() RideSharingSystem {
return RideSharingSystem{
t: 0,
riders: redblacktree.New[int, int](),
drivers: redblacktree.New[int, int](),
d: make(map[int]int),
}
}
func (this *RideSharingSystem) AddRider(riderId int) {
this.d[riderId] = this.t
this.riders.Put(this.t, riderId)
this.t++
}
func (this *RideSharingSystem) AddDriver(driverId int) {
this.drivers.Put(this.t, driverId)
this.t++
}
func (this *RideSharingSystem) MatchDriverWithRider() []int {
if this.riders.Empty() || this.drivers.Empty() {
return []int{-1, -1}
}
driverTime, driverId := this.drivers.Left().Key, this.drivers.Left().Value
riderTime, riderId := this.riders.Left().Key, this.riders.Left().Value
this.drivers.Remove(driverTime)
this.riders.Remove(riderTime)
return []int{driverId, riderId}
}
func (this *RideSharingSystem) CancelRider(riderId int) {
time, exists := this.d[riderId]
if !exists {
return
}
this.riders.Remove(time)
}
/**
* Your RideSharingSystem object will be instantiated and called as such:
* obj := Constructor();
* obj.AddRider(riderId);
* obj.AddDriver(driverId);
* param_3 := obj.MatchDriverWithRider();
* obj.CancelRider(riderId);
*/
# Accepted solution for LeetCode #3829: Design Ride Sharing System
class RideSharingSystem:
def __init__(self):
self.t = 0
self.riders = SortedList()
self.drivers = SortedList()
self.d = defaultdict(int)
def addRider(self, riderId: int) -> None:
self.d[riderId] = self.t
self.riders.add((self.t, riderId))
self.t += 1
def addDriver(self, driverId: int) -> None:
self.drivers.add((self.t, driverId))
self.t += 1
def matchDriverWithRider(self) -> List[int]:
if len(self.riders) < 1 or len(self.drivers) < 1:
return [-1, -1]
return [self.drivers.pop(0)[1], self.riders.pop(0)[1]]
def cancelRider(self, riderId: int) -> None:
self.riders.discard((self.d[riderId], riderId))
# Your RideSharingSystem object will be instantiated and called as such:
# obj = RideSharingSystem()
# obj.addRider(riderId)
# obj.addDriver(driverId)
# param_3 = obj.matchDriverWithRider()
# obj.cancelRider(riderId)
// Accepted solution for LeetCode #3829: Design Ride Sharing System
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #3829: Design Ride Sharing System
// class RideSharingSystem {
// private int t;
// private TreeSet<int[]> riders;
// private TreeSet<int[]> drivers;
// private Map<Integer, Integer> d;
//
// public RideSharingSystem() {
// this.t = 0;
// this.riders = new TreeSet<>(
// (a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1]));
// this.drivers = new TreeSet<>(
// (a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1]));
// this.d = new HashMap<>();
// }
//
// public void addRider(int riderId) {
// d.put(riderId, t);
// riders.add(new int[] {t, riderId});
// t++;
// }
//
// public void addDriver(int driverId) {
// drivers.add(new int[] {t, driverId});
// t++;
// }
//
// public int[] matchDriverWithRider() {
// if (riders.isEmpty() || drivers.isEmpty()) {
// return new int[] {-1, -1};
// }
// int driverId = drivers.pollFirst()[1];
// int riderId = riders.pollFirst()[1];
// return new int[] {driverId, riderId};
// }
//
// public void cancelRider(int riderId) {
// Integer time = d.get(riderId);
// if (time != null) {
// riders.remove(new int[] {time, riderId});
// }
// }
// }
//
// /**
// * Your RideSharingSystem object will be instantiated and called as such:
// * RideSharingSystem obj = new RideSharingSystem();
// * obj.addRider(riderId);
// * obj.addDriver(driverId);
// * int[] param_3 = obj.matchDriverWithRider();
// * obj.cancelRider(riderId);
// */
// Accepted solution for LeetCode #3829: Design Ride Sharing System
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #3829: Design Ride Sharing System
// class RideSharingSystem {
// private int t;
// private TreeSet<int[]> riders;
// private TreeSet<int[]> drivers;
// private Map<Integer, Integer> d;
//
// public RideSharingSystem() {
// this.t = 0;
// this.riders = new TreeSet<>(
// (a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1]));
// this.drivers = new TreeSet<>(
// (a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1]));
// this.d = new HashMap<>();
// }
//
// public void addRider(int riderId) {
// d.put(riderId, t);
// riders.add(new int[] {t, riderId});
// t++;
// }
//
// public void addDriver(int driverId) {
// drivers.add(new int[] {t, driverId});
// t++;
// }
//
// public int[] matchDriverWithRider() {
// if (riders.isEmpty() || drivers.isEmpty()) {
// return new int[] {-1, -1};
// }
// int driverId = drivers.pollFirst()[1];
// int riderId = riders.pollFirst()[1];
// return new int[] {driverId, riderId};
// }
//
// public void cancelRider(int riderId) {
// Integer time = d.get(riderId);
// if (time != null) {
// riders.remove(new int[] {time, riderId});
// }
// }
// }
//
// /**
// * Your RideSharingSystem object will be instantiated and called as such:
// * RideSharingSystem obj = new RideSharingSystem();
// * obj.addRider(riderId);
// * obj.addDriver(driverId);
// * int[] param_3 = obj.matchDriverWithRider();
// * obj.cancelRider(riderId);
// */
Use this to step through a reusable interview workflow for this problem.
Use a simple list or array for storage. Each operation (get, put, remove) requires a linear scan to find the target element — O(n) per operation. Space is O(n) to store the data. The linear search makes this impractical for frequent operations.
Design problems target O(1) amortized per operation by combining data structures (hash map + doubly-linked list for LRU, stack + min-tracking for MinStack). Space is always at least O(n) to store the data. The challenge is achieving constant-time operations through clever structure composition.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.