Coding questions · Uber
Find earliest time all riders become connected
Assesses understanding of graph connectivity, temporal event processing, and dynamic graph data-structures for determining when a set of nodes becomes a single connected component.
You are given a time-ordered log of events involving Uber riders. Each event has a timestamp and two rider names.
Event types:
t X shared-ride-with Y— ridersXandYshared a ride at timet, which creates an (undirected) connection between them.
Two riders are considered connected if there is a path of shared rides between them (transitive connectivity). For example, if A shared with B and B shared with C, then A is connected to C.
Example (already sorted by time):
t1 Alice shared-ride-with Bobt2 Charlie shared-ride-with Dant3 Bob shared-ride-with Charliet4 Alice shared-ride-with Evet5 Bob shared-ride-with Dan
Task:
- Return the earliest timestamp at which all riders that appear in the logs become connected in a single connected component. If this never happens, return an appropriate value (e.g.,
-1).
Follow-up: The log may also contain block events:
t X blocked Y— starting at timet, treat ridersXandYas no longer directly connected by their shared-ride relationship (i.e., the edge betweenXandYis removed for times>= t, even if they shared earlier).
How would you modify your approach to still find the earliest time when all riders are connected, given that connections can be both added (shared-ride-with) and removed (blocked)?
Part 1: Earliest Time All Riders Become Connected
You are given a time-ordered list of shared-ride events. Each event is a tuple (timestamp, rider_a, rider_b) meaning rider_a and rider_b shared a ride at that time, creating an undirected connection between them. Two riders are considered connected if there is a path of shared rides between them. Return the earliest timestamp at which all riders that appear anywhere in the log belong to a single connected component. If this never happens, return -1.
Constraints
0 <= len(events) <= 2 * 10^5- Timestamps are strictly increasing integers.
rider_aandrider_bare non-empty strings.rider_a != rider_bfor every event.- All riders that appear anywhere in the log must be considered when deciding connectivity.
Examples
Example 1
Input: [(1, 'Alice', 'Bob'), (2, 'Charlie', 'Dan'), (3, 'Bob', 'Charlie'), (4, 'Alice', 'Eve'), (5, 'Bob', 'Dan')]
Output: 4
Explanation: After time 3, Alice/Bob/Charlie/Dan are connected, but Eve is still separate. At time 4, Eve joins the same component, so the answer is 4.
Example 2
Input: [(1, 'A', 'B'), (2, 'A', 'B'), (3, 'B', 'C')]
Output: 3
Explanation: The duplicate edge at time 2 changes nothing. All three riders become connected at time 3.
Hints
- Model riders as nodes in an undirected graph, and process edges in time order.
- If you know the full set of riders in advance, a Disjoint Set Union (Union-Find) can track how many connected components remain.
Part 2: Earliest Time All Riders Become Connected with Shared and Blocked Events
You are given a time-ordered list of rider events. Each event is a tuple (timestamp, action, rider_a, rider_b). If action == 'shared', riders rider_a and rider_b become directly connected from that time onward. If action == 'blocked', the direct edge between rider_a and rider_b is removed from that time onward. A later shared event for the same pair can add the edge again. Connectivity is still transitive through other riders. Return the earliest timestamp at which all riders that appear anywhere in the full log are connected at the same time. If this never happens, return -1.
Constraints
0 <= len(events) <= 2 * 10^5- Timestamps are strictly increasing integers.
actionis either'shared'or'blocked'.rider_aandrider_bare non-empty strings, andrider_a != rider_b.- The same pair may appear many times.
- A
blockedevent for a pair that is not currently active has no effect. - All riders that appear anywhere in the log, including riders that only appear in block events, count toward the final connectivity check.
Examples
Example 1
Input: [(1, 'shared', 'Alice', 'Bob'), (2, 'shared', 'Charlie', 'Dan'), (3, 'shared', 'Bob', 'Charlie'), (4, 'blocked', 'Alice', 'Bob')]
Output: 3
Explanation: At time 3, all four riders are connected. The later block at time 4 breaks one direct edge, but the earliest successful time is still 3.
Example 2
Input: [(1, 'shared', 'A', 'B'), (2, 'shared', 'B', 'C'), (3, 'blocked', 'B', 'C'), (4, 'shared', 'C', 'A')]
Output: 2
Explanation: All riders are already connected at time 2. Even though they disconnect later and reconnect again, the earliest valid time is 2.
Hints
- A normal Union-Find handles edge additions well, but not deletions. Try processing the problem offline instead of updating one mutable graph directly.
- Think about the time interval during which each edge is active, then add that edge to a segment tree over time and use a rollback DSU while traversing it.