Network Delay Time
Table of Contents + −
You send a signal from one computer in a network. The signal spreads to other computers along wires. Each wire takes some time. You want to know how long until every computer has the signal. This is really a shortest path question in disguise. So it is the perfect place to learn Dijkstra’s algorithm, which shows up in interviews all the time.
🎯 The Problem
You send a signal from one node. You must find how long until every node has it.
The rules:
- You get
nnodes, numbered1ton. - You get travel times. Each entry
[u, v, w]means a signal goes fromutovinwtime. - The edges are one-way.
- The signal starts at node
k. - Return the time for the slowest node to receive it.
- If some node can never be reached, return
-1.
Input: times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2Output: 2
Explanation: From node 2 the signal reaches node 1 in time 1,node 3 in time 1, and node 4 in time 2. The slowest is 2.The shortest time to reach a node is its shortest path from the start. A shortest path is the route with the smallest total cost. The answer is the largest shortest path among all nodes. Here is the network for the example.
🐢 Approach 1: Try Every Route (Brute Force)
The idea in one line: list every route from the start to each node and keep the shortest.
The idea:
- From the start, walk out along edges in every possible way.
- Record the total time of each full route to a node.
- For each node, keep its smallest route time.
Why it is weak:
- The number of routes explodes as the network grows.
- The same edges get walked again and again across routes.
- Far too slow on any real network.
Here is the route-relaxation code:
def network_delay_time(times, n, k): dist = [float("inf")] * (n + 1); dist[k] = 0 for _ in range(n - 1): for u, v, w in times: if dist[u] + w < dist[v]: dist[v] = dist[u] + w ans = max(dist[1:]) return -1 if ans == float("inf") else ans🔁 Approach 2: Bellman-Ford (Better)
The idea in one line: relax every edge over and over until the distances stop improving.
The idea:
- Bellman-Ford keeps a best-known distance for every node.
- Relaxing an edge means: if going through it gives a shorter distance, update it.
How it works:
- Set the start distance to zero and the rest to infinity.
- Relax every edge once. Repeat that whole pass up to
n - 1times. - After the passes settle, every distance is final.
Why pick it sometimes:
- It works even when edge weights are negative.
Why it is weak here:
- It relaxes every edge in every pass.
- That is O(V times E), more work than needed when all weights are positive.
Here is Bellman-Ford:
def network_delay_time(times, n, k): dist = [float("inf")] * (n + 1); dist[k] = 0 for _ in range(n - 1): changed = False for u, v, w in times: if dist[u] + w < dist[v]: dist[v] = dist[u] + w; changed = True if not changed: break ans = max(dist[1:]) return -1 if ans == float("inf") else ans⚡ Approach 3: Dijkstra’s Algorithm (Best)
The idea in one line: always settle the closest unsettled node next, using a min-heap.
The idea:
- Dijkstra’s algorithm finds the shortest path from one start to all nodes.
- A min-heap is a structure that hands you the smallest item quickly.
How it works:
- Set every distance to infinity, except the start at zero. Push the start into the heap.
- Pull the node with the smallest distance. That distance is now final.
- It is final because all weights are positive, so no later path can beat it.
- For each neighbor, if going through this node is shorter, update it and push it.
- Keep going until the heap is empty.
- The answer is the largest settled distance. If a node is still infinity, return
-1.
Why it is fast:
- Each node settles once. Each edge is pushed once.
- Each heap step costs about log of its size, giving O(E log V).
Here is the order Dijkstra’s settles the nodes on the example, each with its final shortest time.
Steps to Solve
- Build a map from each node to its list of
[neighbor, time]edges. - Set every node’s distance to infinity, except the start node which is zero.
- Push the start node into a min-heap with distance zero.
- Pull the closest node. If you already settled it with a smaller distance, skip it.
- For each neighbor, if going through this node is shorter, update it and push it.
- When the heap is empty, take the largest distance. If any node is unreached, return
-1.
This Python version uses heapq, the built-in min-heap, to always pull the closest node next.
import heapqfrom collections import defaultdict
def network_delay_time(times, n, k): graph = defaultdict(list) for u, v, w in times: graph[u].append((v, w)) # node -> (neighbor, time)
dist = {} heap = [(0, k)] # (distance, node) while heap: d, u = heapq.heappop(heap) # closest unsettled node if u in dist: continue # already settled dist[u] = d for v, w in graph[u]: if v not in dist: heapq.heappush(heap, (d + w, v))
if len(dist) < n: return -1 # some node never reached return max(dist.values()) # slowest arrival
times = [[2, 1, 1], [2, 3, 1], [3, 4, 1]]print(network_delay_time(times, 4, 2))The output of the above code will be:
2Let us read the Python version line by line and understand each choice.
graph = defaultdict(list)for u, v, w in times: graph[u].append((v, w))We turn the edge list into an adjacency map. Adjacency map means each node points to the list of its direct neighbors and the time to reach them. This lets us find a node’s neighbors instantly instead of scanning all edges.
dist = {}heap = [(0, k)]dist holds the final shortest time for each settled node. The heap starts with the start node k at distance zero. We store pairs as (distance, node) so the heap orders by distance first.
while heap: d, u = heapq.heappop(heap) if u in dist: continue dist[u] = dWe pop the closest unsettled node. If it is already in dist, we settled it earlier with a smaller distance, so we skip this stale copy. Otherwise this popped distance is its final shortest time. Because all weights are positive, nothing later can reach it faster.
for v, w in graph[u]: if v not in dist: heapq.heappush(heap, (d + w, v))For each neighbor v not yet settled, we push a new candidate distance d + w. We do not remove old heap entries. Instead the if u in dist check above ignores any stale copies when they surface.
if len(dist) < n: return -1return max(dist.values())If we settled fewer nodes than n, some node was unreachable, so we return -1. Otherwise the answer is the largest shortest distance, which is the slowest node to get the signal.
⏱️ Time and Space Complexity
Let V be the number of nodes and E the number of edges. Dijkstra’s with a heap settles each node once and pushes each edge once. Each heap operation costs about log of its size. So the total time is O(E log V). The space holds the graph, the distances, and the heap, which is O(V + E). Bellman-Ford would be O(V times E), which is slower here.
| Approach | Time Complexity | Space Complexity |
|---|---|---|
| Try every route (brute force) | Exponential | O(V) |
| Bellman-Ford | O(V × E) | O(V) |
| Dijkstra with a min-heap | O(E log V) | O(V + E) |
Tip
Dijkstra’s algorithm only works when all edge weights are positive. If the graph can have negative weights, reach for Bellman-Ford instead. Saying this out loud in an interview shows you know the limits of your tool.
🧩 Key Takeaways
- ✅ Network Delay Time is a shortest path problem, and the answer is the largest shortest path.
- ✅ Dijkstra’s algorithm settles the closest unsettled node first using a min-heap.
- ✅ A popped distance is final because all edge weights are positive.
- ✅ Skip stale heap entries by checking if a node is already settled.
- ✅ It runs in O(E log V) time, faster than Bellman-Ford for positive weights.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does the answer to Network Delay Time represent?
Why: All nodes get the signal once the slowest of them does, which is the maximum shortest path.
- 2
Why can Dijkstra's treat a popped distance as final?
Why: With positive weights, the smallest distance pulled from the heap cannot be beaten later.
- 3
When should you use Bellman-Ford instead of Dijkstra's?
Why: Bellman-Ford handles negative weights, which Dijkstra's cannot.
- 4
What is the time complexity of Dijkstra's with a min-heap?
Why: Each edge is pushed once and each heap operation costs log V, giving O(E log V).