Floyd Warshall All Pairs Shortest Path in DSA Typescript - Time & Space Complexity
We want to understand how the time needed to find shortest paths between all pairs of points grows as the number of points increases.
How does the running time change when the graph size grows?
Analyze the time complexity of the following code snippet.
function floydWarshall(graph: number[][]): number[][] {
const dist = graph.map(row => row.slice());
const n = graph.length;
for (let k = 0; k < n; k++) {
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
return dist;
}
This code finds the shortest distances between every pair of points in a graph using three nested loops.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The triple nested loops that update distances.
- How many times: Each loop runs from 0 to n-1, so the innermost operation runs about n x n x n = n³ times.
As the number of points (n) grows, the number of operations grows very fast because every pair of points is checked for every possible intermediate point.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 1,000 |
| 100 | 1,000,000 |
| 1000 | 1,000,000,000 |
Pattern observation: When n increases ten times, operations increase about a thousand times (n³ growth).
Time Complexity: O(n³)
This means the time needed grows very quickly as the graph size grows, roughly proportional to the cube of the number of points.
[X] Wrong: "Since there are three loops, the time complexity is O(n) because loops run one after another."
[OK] Correct: The loops are nested, not sequential, so the total operations multiply, making it O(n³), not just O(n).
Understanding this algorithm's time complexity helps you explain how nested loops affect performance and why some algorithms are slower on bigger inputs. This skill is valuable for solving real problems efficiently.
"What if we replaced the triple nested loops with a recursive approach that splits the graph? How might that affect the time complexity?"
Practice
Solution
Step 1: Single-source vs all-pairs
Dijkstra/Bellman-Ford compute shortest paths from ONE source to all others. To get all-pairs with Dijkstra, run it V times = O(V(E + V log V)).Step 2: Floyd-Warshall
Floyd-Warshall computes shortest paths between every pair (i,j) in a single O(V³) pass. Simpler to implement for dense graphs.Final Answer:
All-pairs shortest paths in one pass. -> Option BQuick Check:
Floyd-Warshall = all-pairs. Dijkstra = single-source. [OK]
- Confusing with Dijkstra (single-source)
- Thinking it finds MST
- Confusing with topological sort
Solution
Step 1: Core idea
For each intermediate vertex k: is the path i→k→j shorter than the current best i→j?Step 2: Recurrence
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]). Keep the minimum of: current best OR going through k.Final Answer:
min(dist[i][j], dist[i][k] + dist[k][j]) -> Option BQuick Check:
Always take the minimum - relaxation. [OK]
- Using + without min (overwrites current best)
- Using max instead of min
- Multiplying instead of adding edge weights
Solution
Step 1: Self-distance
dist[i][i] = 0 - zero cost to stay at the same vertex.Step 2: No edge
dist[i][j] = Infinity when no direct edge exists - represents unreachable initially. In TypeScript: Infinity works correctly with Math.min().Final Answer:
dist[i][i]=0, no edge=Infinity -> Option BQuick Check:
Self=0, no edge=Infinity. Infinity + x = Infinity in JS - works with min(). [OK]
- Using -1 for no edge (breaks min comparison)
- Setting self-distance to Infinity
- Using 0 for no edge (treats as zero-weight edge)
Solution
Step 1: Why k is outermost
k is the intermediate vertex being 'unlocked' at each outer iteration. When we process intermediate k, all pairs i→j must be relaxed using k.Step 2: Correctness
If k is innermost, we might use a later-unlocked vertex when relaxing - violating the DP ordering. k must be outermost so all (i,j) pairs are fully relaxed before moving to k+1.Final Answer:
k outermost, then i, then j. -> Option BQuick Check:
Floyd-Warshall loop order: k→i→j. k must be outermost. [OK]
- Putting i outermost (most common mistake)
- Putting j outermost
- Any order other than k→i→j gives wrong results
Solution
Step 1: Negative cycle effect
If a negative cycle exists reachable from i back to i, the shortest path dist[i][i] will become negative (going around the cycle reduces cost below 0).Step 2: Detection
After the algorithm completes, check: for any i, if dist[i][i] < 0, a negative cycle exists involving i.Final Answer:
Check dist[i][i] < 0 for any i. -> Option BQuick Check:
Negative cycle: dist[i][i] < 0 after Floyd-Warshall. [OK]
- Checking dist[i][j] for non-self pairs
- Summing all distances
- Running algorithm twice
Ready to prove it?
Pass the test and this pattern moves unknown
