Graphs
Overview
The Core Question
What do I know about the edge weights?
| Graph Type | Algorithm | Time Complexity |
|---|---|---|
| Unweighted (all edges = 1) | BFS | O(V + E) |
| Non-negative weights | Dijkstra | O((V + E) log V) |
| Negative weights allowed | Bellman-Ford | O(V · E) |
| All pairs, small graph | Floyd-Warshall | O(V³) |
1. BFS: When All Edges Are Equal
Walkthrough
def bfs_shortest_path(graph, start):distances = {start: 0}queue = deque([start])while queue:node = queue.popleft()for neighbor in graph[node]:if neighbor not in distances:distances[neighbor] = distances[node] + 1queue.append(neighbor)return distances
BFS shortest path
0 / 12
Complexity
When to Use BFS
- Grid navigation (moving up/down/left/right)
- Unweighted graph traversal
- Finding minimum number of steps/moves
Problems That Use BFS for Shortest Path
- Minimum Knight Moves — Classic grid BFS
- Rotting Oranges — Multi-source BFS
- 01-Matrix — Distance from each cell to nearest 0
2. Dijkstra's Algorithm: The Workhorse
Walkthrough
def dijkstra(graph, start):distances = {start: 0}heap = [(0, start)]while heap:dist, node = heapq.heappop(heap)if dist > distances.get(node, float('inf')):continuefor neighbor, weight in graph[node]:new_dist = dist + weightif new_dist < distances.get(neighbor, float('inf')):distances[neighbor] = new_distheapq.heappush(heap, (new_dist, neighbor))return distances
Dijkstra's algorithm
0 / 25
Why It Works
Complexity
- Each node is added to the heap at most once: O(V log V)
- Each edge might trigger a heap update: O(E log V)
When to Use Dijkstra
- Weighted graphs with non-negative edges
- Finding shortest path from one source to all nodes
- Problems involving "minimum cost" or "minimum time"
Classic Dijkstra Problems
- Network Delay Time — How long until all nodes receive a signal?
- Path With Minimum Effort — Minimize the maximum height difference along the path
- Cheapest Flights Within K Stops — Shortest path with a constraint (uses modified state)
3. Bellman-Ford: When Negative Weights Exist
Walkthrough
def bellman_ford(edges, n, start):distances = [float('inf')] * ndistances[start] = 0for _ in range(n - 1):for u, v, weight in edges:if distances[u] + weight < distances[v]:distances[v] = distances[u] + weight# Check for negative cyclesfor u, v, weight in edges:if distances[u] + weight < distances[v]:return None # Negative cyclereturn distances
Bellman-Ford algorithm
0 / 16
Why V-1 Iterations?
Complexity
When to Use Bellman-Ford
- Graph has negative edge weights
- Need to detect negative cycles
- Problems involving arbitrage or exchange rates
4. Floyd-Warshall: All Pairs Shortest Path
Walkthrough
def floyd_warshall(graph, n):dist = [[float('inf')] * n for _ in range(n)]for i in range(n):dist[i][i] = 0for u, v, w in graph:dist[u][v] = wfor k in range(n):for i in range(n):for j in range(n):if dist[i][k] + dist[k][j] < dist[i][j]:dist[i][j] = dist[i][k] + dist[k][j]return dist
Floyd-Warshall algorithm
0 / 90
The Key Insight
Complexity
When to Use Floyd-Warshall
- Need distances between all pairs
- Small number of nodes (V ≤ 400 or so)
- Dense graphs where E ≈ V²
Classic Floyd-Warshall Problem
- Find the City With the Smallest Number of Neighbors at a Threshold Distance — Count reachable cities for each starting city
Quick Reference
Algorithm Selection
| Situation | Use This |
|---|---|
| All edges weight 1 | BFS |
| Different positive weights | Dijkstra |
| Negative weights possible | Bellman-Ford |
| Need all pairs | Floyd-Warshall |
| Weights are 0 or 1 only | 0-1 BFS (optimization) |
Complexity Comparison
| Algorithm | Time | Space |
|---|---|---|
| BFS | O(V + E) | O(V) |
| Dijkstra | O((V + E) log V) | O(V) |
| Bellman-Ford | O(V · E) | O(V) |
| Floyd-Warshall | O(V³) | O(V²) |
Common Interview Patterns
Pattern 1: Modified State
- "Cheapest flights with at most K stops" — State is (node, stops_remaining)
- "Shortest path with keys and doors" — State is (node, keys_collected)
Pattern 2: Multi-Source BFS
- Add all sources to the queue initially
- BFS will naturally find the closest source for each node
Pattern 3: Reverse Thinking
- Instead of "shortest path from A to B", think "shortest path from B to A"
- Instead of "can I reach the target?", think "which nodes can reach the target?"
Key Takeaways
- BFS handles unweighted graphs — It's simpler than you think. Many "shortest path" problems are just BFS.
- Dijkstra is your default for weighted graphs — Learn it cold. It appears in ~70% of weighted shortest path interview problems.
- Know when algorithms fail — Dijkstra fails with negative weights. BFS fails with varying weights. Understanding why is more valuable than memorizing implementations.
- State modification is common — Real interview problems often add constraints that require tracking extra state beyond just the current node.
The best mocks on the market.
Now up to 15% off
On This Page
The Core Question
1. BFS: When All Edges Are Equal
Walkthrough
Complexity
When to Use BFS
Problems That Use BFS for Shortest Path
2. Dijkstra's Algorithm: The Workhorse
Walkthrough
Why It Works
Complexity
When to Use Dijkstra
Classic Dijkstra Problems
3. Bellman-Ford: When Negative Weights Exist
Walkthrough
Why V-1 Iterations?
Complexity
When to Use Bellman-Ford
4. Floyd-Warshall: All Pairs Shortest Path
Walkthrough
The Key Insight
Complexity
When to Use Floyd-Warshall
Classic Floyd-Warshall Problem
Quick Reference
Algorithm Selection
Complexity Comparison
Common Interview Patterns
Pattern 1: Modified State
Pattern 2: Multi-Source BFS
Pattern 3: Reverse Thinking
Key Takeaways