Algorithms

Shortest Path Algorithms

Finding the shortest path between two points is one of computing's most practical problems. GPS navigation, network routing, game AI pathfinding, and social network analysis all rely on shortest path algorithms. This article covers the four essential algorithms: Dijkstra's for non-negative weights, Bellman-Ford for negative weights, Floyd-Warshall for all pairs, and A* for heuristic-guided search.

๐Ÿ“‹ At a Glance

AlgorithmTimeSpaceHandles NegativeBest For
Dijkstra (binary heap)O((V+E) log V)O(V)NoSingle source, non-negative
Bellman-FordO(VE)O(V)Yes (detects cycles)Negative weights
Floyd-WarshallO(Vยณ)O(Vยฒ)Yes (detects cycles)All pairs, dense graphs
A*O(E) best, O(Vยฒ) worstO(V)NoSingle pair with heuristic

๐ŸŽฏ What You'll Learn

After reading this article, you will be able to:

  • Implement Dijkstra's algorithm with proper priority queue usage
  • Handle negative weights using Bellman-Ford
  • Compute all-pairs shortest paths with Floyd-Warshall
  • Apply A search* with admissible heuristics
  • Detect negative cycles that make shortest path undefined
  • Choose the right algorithm based on graph characteristics

๐Ÿ”ฅ Production Story: The Logistics Routing Disaster

A delivery company's routing system calculated optimal routes for 500 daily deliveries. After adding "discount roads" with negative costs (toll rebates), the system started producing impossible routes.

JAVA(33 lines)
Code
Loading syntax highlighter...
The problem: Dijkstra assumes once a vertex is processed, its distance is final. Negative edges violate this assumption - a "longer" path through negative edges might be shorter!
TEXT(12 lines)
Code
Loading syntax highlighter...
The fix:
JAVA(53 lines)
Code
Loading syntax highlighter...
The lesson: Algorithm selection isn't just about performance - it's about correctness. Using Dijkstra on negative-weight graphs gives wrong answers silently.

๐Ÿง  Mental Model: Shortest Path Algorithm Selection

TEXT(23 lines)
Code
Loading syntax highlighter...

๐Ÿ”ฌ Deep Dive: Dijkstra's Algorithm

๐ŸŽฎ Try It Yourself

Watch Dijkstra's algorithm find shortest paths step by step. Observe how the algorithm greedily selects the minimum distance vertex and relaxes edges:

Loading visualizer...

The Greedy Insight

Dijkstra works by greedily selecting the unvisited vertex with minimum distance. With non-negative weights, this greedy choice is always correct.

TEXT(14 lines)
Code
Loading syntax highlighter...

Implementation with Priority Queue

JAVA(98 lines)
Code
Loading syntax highlighter...

Dijkstra with Indexed Priority Queue (Optimized)

JAVA(106 lines)
Code
Loading syntax highlighter...

๐Ÿ”ฌ Deep Dive: Bellman-Ford Algorithm

Handling Negative Weights

JAVA(110 lines)
Code
Loading syntax highlighter...

Why Bellman-Ford Works

TEXT(16 lines)
Code
Loading syntax highlighter...

๐Ÿ”ฌ Deep Dive: Floyd-Warshall Algorithm

All-Pairs Shortest Paths

JAVA(112 lines)
Code
Loading syntax highlighter...

Floyd-Warshall DP Insight

TEXT(21 lines)
Code
Loading syntax highlighter...

๐Ÿ”ฌ Deep Dive: A* Search Algorithm

The Heuristic Advantage

A* uses a heuristic function h(v) to estimate distance from v to goal, prioritizing vertices that seem closer to the goal.

JAVA(75 lines)
Code
Loading syntax highlighter...

Common Heuristics

JAVA(35 lines)
Code
Loading syntax highlighter...

A* vs Dijkstra Visualization

TEXT(17 lines)
Code
Loading syntax highlighter...

Meeting in the Middle

JAVA(87 lines)
Code
Loading syntax highlighter...

โš ๏ธ Common Mistakes

Mistake 1: Using Dijkstra with Negative Weights

JAVA(10 lines)
Code
Loading syntax highlighter...

Mistake 2: Integer Overflow in Distance Calculation

JAVA(15 lines)
Code
Loading syntax highlighter...

Mistake 3: Not Handling Disconnected Vertices

JAVA(10 lines)
Code
Loading syntax highlighter...

Mistake 4: Wrong Heuristic in A*

JAVA(10 lines)
Code
Loading syntax highlighter...

๐Ÿ› Debug This: The Broken Shortest Path

These implementations have bugs. Find and fix them:

JAVA(65 lines)
Code
Loading syntax highlighter...
๐Ÿ’ก Hint

Look for:

  1. Initialization of distances
  2. Loop count in Bellman-Ford
  3. Missing negative cycle check
  4. A* should sort by f-score (g + h), not just g-score
โœ… Solution
JAVA(84 lines)
Code
Loading syntax highlighter...
Bugs explained:
  1. Dijkstra initialization: dist[i] = graph[src][i] only works if all vertices have direct edges from source. Should initialize to MAX_VALUE and start with source at 0.
  2. Bellman-Ford iterations: Should be V-1 iterations for relaxation, then one more iteration to detect negative cycles. Original had V iterations and no cycle check.
  3. A sorting*: A* must sort by f-score (g + h), not just g-score. Sorting by g-score alone makes it equivalent to Dijkstra, losing the heuristic benefit.

๐Ÿ’ป Exercises

Exercise 1: Network Delay Time (LeetCode 743) โญโญ

Find time for signal to reach all nodes from source.

JAVA(11 lines)
Code
Loading syntax highlighter...

Exercise 2: Cheapest Flights Within K Stops (LeetCode 787) โญโญโญ

Find cheapest flight with at most K stops.

JAVA(12 lines)
Code
Loading syntax highlighter...
๐Ÿ’ก Hint

Use Bellman-Ford with exactly k+1 iterations (k stops = k+1 edges). Or use BFS with level tracking.


Exercise 3: Path with Maximum Probability (LeetCode 1514) โญโญโญ

Find path with highest probability of success.

JAVA(11 lines)
Code
Loading syntax highlighter...

Exercise 4: Shortest Path in Grid with Obstacles (LeetCode 1293) โญโญโญโญ

Find shortest path in grid where you can eliminate up to k obstacles.

JAVA(10 lines)
Code
Loading syntax highlighter...

Exercise 5: Find Negative Cycle โญโญโญโญ

Return the actual vertices forming a negative cycle.

JAVA(9 lines)
Code
Loading syntax highlighter...

๐ŸŽค Interview Questions

Question 1: When would you use each shortest path algorithm?

Answer:
AlgorithmUse When
BFSUnweighted graph, need shortest by edge count
DijkstraWeighted, non-negative, single source
A*Single source-target with good heuristic
Bellman-FordHas negative weights, need cycle detection
Floyd-WarshallNeed all-pairs, dense graph, V is small
Decision factors:
  1. Negative weights? โ†’ Bellman-Ford or Floyd-Warshall
  2. Single source or all pairs?
  3. Graph density (E vs Vยฒ)?
  4. Have good heuristic? โ†’ Consider A*

Question 2: Why doesn't Dijkstra work with negative weights?

Answer:

Dijkstra's greedy approach assumes: "Once a vertex is processed, its distance is final."

With negative weights, this assumption breaks:

TEXT(17 lines)
Code
Loading syntax highlighter...

Question 3: Explain the A* heuristic requirements

Answer:
A* requires an admissible heuristic: h(v) โ‰ค actual distance from v to goal.
Why admissibility matters:
  • If h overestimates, A* might skip the optimal path
  • Admissible h guarantees optimal solution
Consistency/Monotonicity (stronger): h(u) โ‰ค cost(u,v) + h(v)
  • Guarantees A* won't revisit nodes
  • All consistent heuristics are admissible
Common heuristics:
  • Manhattan: |dx| + |dy| - admissible for 4-direction grid
  • Euclidean: โˆš(dxยฒ + dyยฒ) - admissible for any movement
  • Zero: h(v) = 0 - always admissible, but A* becomes Dijkstra
Trade-off: Higher h (closer to actual) โ†’ fewer nodes explored, but more computation per node.

Question 4: How would you detect a negative cycle?

Answer:
Method 1: Bellman-Ford extra iteration
JAVA(6 lines)
Code
Loading syntax highlighter...
Method 2: Floyd-Warshall diagonal check
JAVA(6 lines)
Code
Loading syntax highlighter...
Method 3: DFS with path tracking
  • Track sum of edge weights on current DFS path
  • If we return to a vertex with lower total weight, negative cycle found
Finding the actual cycle:
  • Run Bellman-Ford V iterations (not V-1)
  • Any vertex updated in V-th iteration is reachable from negative cycle
  • Trace back through predecessors to find cycle

Question 5: Compare single-source algorithms complexity

Answer:
AlgorithmTimeSpaceNotes
BFSO(V+E)O(V)Unweighted only
Dijkstra (binary heap)O((V+E) log V)O(V)No negative weights
Dijkstra (Fibonacci heap)O(E + V log V)O(V)Better for dense graphs
Bellman-FordO(VE)O(V)Handles negative weights
SPFAO(VE) worst, O(E) avgO(V)Optimized Bellman-Ford
Practical guidance:
  • Sparse graph (E โ‰ˆ V): Dijkstra with binary heap
  • Dense graph (E โ‰ˆ Vยฒ): Dijkstra or Bellman-Ford similar
  • Need negative weights: Bellman-Ford
  • Unweighted: Always use BFS

๐Ÿ“‹ Quick Reference

Algorithm Comparison

DijkstraBellman-FordFloyd-WarshallA*
TypeGreedyDPDPHeuristic
Negative edgesNoYesYesNo
Negative cyclesNoDetectsDetectsNo
Single sourceYesYesNo (all pairs)Yes
TimeO((V+E)log V)O(VE)O(Vยณ)O(E) to O(Vยฒ)

Code Templates

JAVA(49 lines)
Code
Loading syntax highlighter...

๐Ÿ“… Review Schedule

DayFocusTime
Day 1Read article, implement Dijkstra60 min
Day 3Implement Bellman-Ford with cycle detection30 min
Day 7Implement A* for grid pathfinding30 min
Day 14Solve LeetCode shortest path problems45 min
Day 30Review and compare algorithm trade-offs20 min

๐Ÿ”— What's Next?

Part 13: Minimum Spanning Tree covers:
  • Union-Find data structure
  • Kruskal's algorithm
  • Prim's algorithm
  • Borลฏvka's algorithm
  • MST applications
Key insight preview: MST asks "connect all vertices with minimum total edge weight" - different from shortest path which asks about paths between specific vertices.

This article is part of the Algorithms Compendium series. For the complete learning path, see Part 0: How to Use This Series.