Katkat

Courier Delivery Cost Tracker

RipplingSoftware Engineer · Technical Screen

Last updated

Design a stateful tracker class to record courier delivery intervals and earnings, query running courier payouts, and calculate peak concurrent active deliveries within a specific time window.

Courier Delivery Cost Tracker

You are building a backend service for an on-demand logistics platform to track courier activity and delivery payouts. Design a class CourierCostTracker that records delivery shifts, maintains courier balances, and analyzes peak delivery concurrency.

Each delivery takes place over a half-open time interval [start_time, end_time) (meaning the courier is active from start_time up until, but not including, end_time) and incurs a set delivery payout.

Implement the CourierCostTracker class:

  • CourierCostTracker(): Initializes the tracker.
  • record_delivery(courier_id: str, start_time: int, end_time: int, fee: int) -> None: Records a completed delivery for courier courier_id active during [start_time, end_time) with an associated payout of fee.
  • get_courier_total(courier_id: str) -> int: Returns the total cumulative payout earned by courier_id. If courier_id has no recorded deliveries, return 0.
  • get_peak_concurrent(window_start: int, window_end: int) -> int: Returns the maximum number of deliveries active at any single point in time t within the query window [window_start, window_end). Deliveries that overlap with the window should be counted only for the portion of time that falls strictly within [window_start, window_end).

Constraints

  • 0 <= start_time < end_time <= 10^9
  • 0 <= window_start < window_end <= 10^9
  • 1 <= fee <= 10^5
  • courier_id consists of lowercase English letters and digits, length between 1 and 30.
  • At most 2,000 calls to record_delivery and get_peak_concurrent combined.
  • At most 10,000 calls to get_courier_total.

Example 1

tracker = CourierCostTracker()
tracker.record_delivery("c1", 10, 30, 25)
tracker.record_delivery("c2", 20, 50, 40)
tracker.record_delivery("c1", 40, 60, 30)

# c1 earned 25 + 30 = 55
assert tracker.get_courier_total("c1") == 55

# c3 has no records
assert tracker.get_courier_total("c3") == 0

# In window [15, 45):
# - Delivery 1 [10, 30) is active in window during [15, 30)
# - Delivery 2 [20, 50) is active in window during [20, 45)
# - Delivery 3 [40, 60) is active in window during [40, 45)
# Peak concurrency occurs between time 20 and 30 (c1, c2), and between 40 and 45 (c2, c1), max is 2.
assert tracker.get_peak_concurrent(15, 45) == 2

# In window [30, 40), only Delivery 2 [20, 50) is active. Peak is 1.
assert tracker.get_peak_concurrent(30, 40) == 1

# In window [70, 100), no deliveries overlap. Peak is 0.
assert tracker.get_peak_concurrent(70, 100) == 0

Example 2

tracker = CourierCostTracker()
tracker.record_delivery("c1", 10, 20, 15)
tracker.record_delivery("c2", 20, 30, 15)

# Because intervals are half-open [10, 20) and [20, 30), they do not overlap at t = 20.
assert tracker.get_peak_concurrent(0, 50) == 1

Hints

Hint 1

Use a hash map to maintain running cumulative earnings per courier so that `get_courier_total` runs in O(1) time.

Hint 2

For `get_peak_concurrent`, filter deliveries that overlap with the query window by checking if `max(start_time, window_start) < min(end_time, window_end)`.

Hint 3

Transform each overlapping delivery interval into a pair of sweep-line events `(+1 at start, -1 at end)` clipped to the query window, then sort events by timestamp to find the maximum prefix sum.

Follow-up questions

  • If `get_peak_concurrent` was called millions of times on historical, immutable delivery data, how would you optimize queries? (e.g., segment trees or coordinate compression with range maximum query structures).
  • How would your design change if deliveries could be canceled or modified after being recorded?
  • Suppose couriers can have multiple assignments simultaneously, but you need to return the peak number of unique couriers active at the same time rather than peak deliveries. How would you solve that?