Design Ride Sharing System

medium queue design data stream

Problem

Design a RideSharingSystem that matches riders with drivers in arrival order. Support four operations: addRider(riderId) and addDriver(driverId) enqueue a rider or driver; matchDriverWithRider() pairs the earliest still-waiting rider with the earliest available driver, removes both, and returns [driverId, riderId] (or [-1, -1] if either queue is empty); and cancelRider(riderId) withdraws a rider's request only if that rider exists and has not already been matched.

Every id is unique within its role and added at most once, so the only twist is making cancellation play nicely with FIFO matching: a canceled rider must never be paired, yet everyone else keeps their place in line.

InputaddRider(3), addDriver(2), addRider(1), match(), addDriver(5), cancelRider(3), match(), match()
Output[2, 3], [5, 1], [-1, -1]
First match pairs driver 2 with rider 3. cancelRider(3) does nothing — rider 3 was already matched. The next match pairs driver 5 with rider 1; the last finds no rider left, so it returns [-1, -1].

from collections import deque

class RideSharingSystem:
    def __init__(self):
        self.riders = deque()     # waiting riders, arrival order
        self.drivers = deque()    # available drivers, arrival order
        self.canceled = set()     # riders canceled before matching
    def addRider(self, riderId):
        self.riders.append(riderId)
    def addDriver(self, driverId):
        self.drivers.append(driverId)
    def matchDriverWithRider(self):
        while self.riders and self.riders[0] in self.canceled:
            self.canceled.discard(self.riders.popleft())
        if not self.riders or not self.drivers:
            return [-1, -1]
        driverId = self.drivers.popleft()
        riderId = self.riders.popleft()
        return [driverId, riderId]
    def cancelRider(self, riderId):
        self.canceled.add(riderId)
class RideSharingSystem {
  constructor() {
    this.riders = [];        // waiting riders, arrival order
    this.drivers = [];       // available drivers, arrival order
    this.head = 0;           // front index into riders
    this.dHead = 0;          // front index into drivers
    this.canceled = new Set(); // canceled rider ids
  }
  addRider(riderId) { this.riders.push(riderId); }
  addDriver(driverId) { this.drivers.push(driverId); }
  matchDriverWithRider() {
    while (this.head < this.riders.length && this.canceled.has(this.riders[this.head])) {
      this.canceled.delete(this.riders[this.head++]);
    }
    if (this.head >= this.riders.length || this.dHead >= this.drivers.length) {
      return [-1, -1];
    }
    const driverId = this.drivers[this.dHead++];
    const riderId = this.riders[this.head++];
    return [driverId, riderId];
  }
  cancelRider(riderId) { this.canceled.add(riderId); }
}
class RideSharingSystem {
    Deque<Integer> riders = new ArrayDeque<>();   // waiting riders
    Deque<Integer> drivers = new ArrayDeque<>();  // available drivers
    Set<Integer> canceled = new HashSet<>();      // canceled rider ids
    public void addRider(int riderId) { riders.addLast(riderId); }
    public void addDriver(int driverId) { drivers.addLast(driverId); }
    public int[] matchDriverWithRider() {
        while (!riders.isEmpty() && canceled.contains(riders.peekFirst())) {
            canceled.remove(riders.pollFirst());
        }
        if (riders.isEmpty() || drivers.isEmpty()) {
            return new int[]{-1, -1};
        }
        int driverId = drivers.pollFirst();
        int riderId = riders.pollFirst();
        return new int[]{driverId, riderId};
    }
    public void cancelRider(int riderId) { canceled.add(riderId); }
}
class RideSharingSystem {
    deque<int> riders;            // waiting riders, arrival order
    deque<int> drivers;           // available drivers, arrival order
    unordered_set<int> canceled;  // canceled rider ids
public:
    void addRider(int riderId) { riders.push_back(riderId); }
    void addDriver(int driverId) { drivers.push_back(driverId); }
    vector<int> matchDriverWithRider() {
        while (!riders.empty() && canceled.count(riders.front())) {
            canceled.erase(riders.front());
            riders.pop_front();
        }
        if (riders.empty() || drivers.empty()) {
            return {-1, -1};
        }
        int driverId = drivers.front(); drivers.pop_front();
        int riderId = riders.front(); riders.pop_front();
        return {driverId, riderId};
    }
    void cancelRider(int riderId) { canceled.insert(riderId); }
};
Time: O(1) amortized per operation Space: O(n)