Coding sample solution

Coding: connected regions and dependencies

How to talk through this coding question, from a first idea to working code, in an interview.

Coding interview · Sample solution in Python · Independent, not affiliated with Uber

The coding question

You're given logs of riders who shared a ride, sorted by time. Return the earliest time when every rider is connected to every other, directly or through other riders, or -1 if that never happens.

Ask a few questions first

AskWhat we'll assume
What does a log look like?A tuple (time, a, b), meaning riders a and b shared a ride at that time.
How do we know who all the riders are?You're given n, and riders are numbered 0 to n - 1.
Does connected carry through other riders?Yes. If a rode with b and b rode with c, then a and c are connected.
What if there's only one rider?They're already connected to everyone, so return 0.

A couple of examples

InputOutput
n = 4, logs [(1, 0, 1), (3, 2, 3), (5, 1, 2)]5, since the ride at time 5 joins {0, 1} and {2, 3}
n = 4, logs [(2, 0, 1), (4, 2, 3)]-1, since the two pairs never meet
n = 3, logs [(1, 0, 1), (2, 1, 0), (6, 1, 2)]6, and the ride at time 2 changes nothing

Start with brute force

After each log, build the graph of rides so far and run a breadth-first search from rider 0. The first time it reaches all n riders, return that log's time.

Cost: a full search after every log is O(m × (n + m)) for m logs. Fine for a few hundred, too slow for 100,000.

A better way

Riders are nodes and rides are edges. It's a graph, even though nobody said graph. We're asking when the whole thing becomes one connected group.

Logs only ever add edges, and they're sorted by time. So keep track of groups as we go with union-find. Start with n groups of one. Each ride either joins two different groups, which drops the count by one, or it's inside a group already and changes nothing. The moment the count hits 1, that's the answer.

  1. Give every rider a parent pointer to themselves, and set groups = n.
  2. find(x) follows parent pointers up to the group's root, shortening the path as it goes.
  3. For each log in order, find the roots of both riders.
  4. If the roots differ, point one at the other and drop groups by one. If groups is now 1, return the time.
  5. If the logs run out with more than one group, return -1.

The code

solution.pypython
def earliest_all_connected(logs, n):
    parent = list(range(n))

    def find(x):
        while parent[x] != x:
            parent[x] = parent[parent[x]]  # point halfway up as we go
            x = parent[x]
        return x

    groups = n
    for time, a, b in logs:
        root_a, root_b = find(a), find(b)
        if root_a != root_b:
            parent[root_a] = root_b
            groups -= 1
            if groups == 1:
                return time
    return -1 if groups > 1 else 0
CostWhy
TimeAbout O(n + m)Each find is close to constant with path shortening, and we do two per log
SpaceO(n)One parent pointer per rider

Test it

Walk through one of the examples out loud, then check the cases that tend to break things:

  • One rider: groups starts at 1, the loop never returns, and we return 0.
  • No logs with two or more riders: groups stays above 1, so -1.
  • The same pair riding twice: the second time, both have the same root and nothing changes.
  • A rider riding with themselves: same root, nothing changes.
  • Everyone connects on the very first log, like n = 2: we return that log's time.

Common mistakes

  • Running a full search after every log, which is the brute force again.
  • Counting distinct riders seen instead of groups. Everyone can show up in a log while still being in two separate groups.
  • Lowering the group count even when both riders already share a root.
  • Forgetting to sort the logs if the interviewer says they might not be sorted.

Follow-up questions

What if the logs aren't sorted?

Sort them by time first. That's O(m log m), and the rest stays the same.

What if they ask for a task order from dependencies instead?

That's a directed graph, so union-find doesn't fit. Count how many tasks each one waits on, start with the ones waiting on nothing, and if tasks are left over at the end, there's a loop.

What if riders can leave a group?

Union-find can't undo a join. If removals are rare, rebuild. Otherwise, process everything in reverse, so removals become joins.

How the time adds up

MinutesWhat you're doing
0–5Ask questions and agree on examples
5–10Brute force and what it costs
10–15Explain the better idea
15–30Write the code
30–38Test it out loud
38–45Follow-up questions

Key concepts used here

We wrote this sample solution ourselves. Practice Loop is independent and isn't affiliated with or endorsed by Uber.