Knowledge Guide
HomeDSAGraphs

Dijkstra's Shortest Path Algorithm

Dijkstra's Shortest Path Algorithm

Dijkstra's algorithm finds shortest paths from one source vertex to every other vertex in a weighted graph by repeatedly pulling the closest not-yet-finalized vertex off a min-heap and using its now-final distance to relax (tighten) its neighbors' distances. Because every edge weight is non-negative, once a vertex is popped from the heap its recorded distance can never be beaten later by some other path through a farther vertex — so that pop is safe to treat as final. It is the same greedy-frontier idea as BFS, generalized from "one hop = one step" to "one hop = arbitrary non-negative cost," with a priority queue replacing the plain FIFO queue so the frontier always expands in true accumulated-cost order rather than arrival order.

Recognize the pattern

Brute force baseline → Dijkstra

Naive baseline (Bellman-Ford style): relax every edge in the graph, repeat that pass |V|−1 times, until no distance improves. This is correct even with negative edges (so long as there is no negative cycle), but it costs O(V·E) because it keeps re-examining edges out of vertices whose shortest distance is already known and settled.

Dijkstra's improvement: exploit non-negativity. Once you pop the minimum-distance vertex from a priority queue, no unexplored edge can ever produce a shorter path to it (all remaining candidate paths pass through vertices that are at least as far away, and adding a non-negative edge cannot make them shorter). So each vertex needs to be finalized exactly once, and each edge needs to be relaxed exactly once, for a total cost of O((V+E) log V) instead of O(V·E). The trade is a bookkeeping structure (the heap) in exchange for never redoing settled work.

Complexity, derived from first principles

Time. Every vertex is popped from the heap; with a lazy-deletion heap (the standard interview-friendly implementation, no decrease-key), every relaxation that improves a distance pushes a fresh (distance, vertex) pair rather than mutating an existing heap entry. Each of the E edges can trigger at most one push, so the heap holds at most O(E) entries over the algorithm's lifetime (plus the O(V) initial pushes). Each push/pop on a heap of size O(E) costs O(log E); since E ≤ V2, log E = O(log V). Total: O(V) pops for the outer loop skeleton plus O(E) pushes/pops for relaxations, each O(log V) → O((V+E) log V). (A decrease-key-capable heap, e.g. a Fibonacci heap, tightens this to O(E + V log V), but is rarely worth the implementation cost in interviews.)

Space. O(V) for the distance array and the finalized/visited array, plus O(E) for the adjacency list and O(E) for the heap in the worst case (one stale entry per relaxation) → O(V + E).

Worked example

Directed graph, source A. Edges: A→B(4), A→C(1), C→B(2), B→D(5), C→D(8), C→E(10), D→E(2).

StepPop (dist, vertex)ActionHeap after step (dist:vertex)
0init dist[A]=0, all others ∞; push (0,A)(0,A)
1(0,A)finalize A; relax B→4, C→1(1,C) (4,B)
2(1,C)finalize C; relax B: 1+2=3<4 → push (3,B); relax D→9; relax E→11(3,B) (4,B)stale (9,D) (11,E)
3(3,B)finalize B; relax D: 3+5=8<9 → push (8,D)(4,B)stale (8,D) (9,D)stale (11,E)
4(4,B)B already finalized → discard, stale entry(8,D) (9,D)stale (11,E)
5(8,D)finalize D; relax E: 8+2=10<11 → push (10,E)(9,D)stale (10,E) (11,E)stale
6(9,D)D already finalized → discard(10,E) (11,E)stale
7(10,E)finalize E; no outgoing edges to relax(11,E)stale
8(11,E)E already finalized → discard, heap empty, done

Final shortest distances from A: A=0, C=1, B=3, D=8, E=10. Two heap entries (4,B) and (9,D) were pushed before a cheaper route was discovered, then popped and thrown away later — that is lazy deletion in action.

Reference implementation (Java)

import java.util.*;

public final class Dijkstra {
    // adj[u] = list of {v, weight} edges out of u
    public static int[] shortestPaths(int n, List<int[]>[] adj, int src) {
        int[] dist = new int[n];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[src] = 0;
        boolean[] done = new boolean[n];
        // min-heap ordered by tentative distance; lazy deletion means we
        // push a fresh entry on every improvement instead of mutating one
        PriorityQueue<long[]> pq = new PriorityQueue<>((a, b) -> Long.compare(a[0], b[0]));
        pq.offer(new long[]{0L, src});

        while (!pq.isEmpty()) {
            long[] top = pq.poll();
            int d = (int) top[0];
            int u = (int) top[1];
            if (done[u]) continue;      // stale heap entry: a shorter path
            done[u] = true;             // already finalized this vertex
            for (int[] edge : adj[u]) {
                int v = edge[0], w = edge[1];
                if (!done[v] && dist[u] != Integer.MAX_VALUE && dist[u] + w < dist[v]) {
                    dist[v] = dist[u] + w;
                    pq.offer(new long[]{dist[v], v});
                }
            }
        }
        return dist; // Integer.MAX_VALUE entries mean unreachable
    }
}

Pitfalls

When to use / when NOT — trade-offs

SituationChoiceWhy
Single source, weighted, all weights ≥ 0DijkstraO((V+E) log V), the standard tool
Single source, some negative weights, no negative cycleBellman-Ford, O(V·E)Dijkstra's greedy finalize-on-pop step is unsound the moment a later edge can subtract enough to beat an already-closed vertex
Unweighted graphPlain BFS, O(V+E)Every edge costs the same "1", so a FIFO queue already visits vertices in non-decreasing distance order — the heap's O(log V) overhead buys nothing
All-pairs shortest paths, dense or need negative edgesFloyd-Warshall O(V3), or Johnson's algorithm (re-weight then run Dijkstra from every vertex)Running Dijkstra V times only works once weights are made non-negative via Johnson's re-weighting; Floyd-Warshall handles negative edges (no negative cycles) directly at the cost of cubic time
Very sparse graph, extreme performance needDijkstra with a Fibonacci heap, O(E + V log V)Removes the log V factor from the E term; rarely worth the implementation complexity outside competitive settings

Takeaways

Recall question: Why does Dijkstra fail on a graph with a negative edge weight even though it uses a priority queue exactly the way BFS uses a plain queue — what specific guarantee does popping the minimum lose?


Authored for this guide; concepts and complexity analysis follow the standard treatment in CLRS (Cormen, Leiserson, Rivest, Stein, "Introduction to Algorithms") Ch. 24, and Sedgewick & Wayne, "Algorithms."

🤖 Don't fully get this? Learn it with Claude

Stuck on Dijkstra's Shortest Path Algorithm? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Dijkstra's Shortest Path Algorithm** (DSA) and want to truly understand it. Explain Dijkstra's Shortest Path Algorithm from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Dijkstra's Shortest Path Algorithm** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Dijkstra's Shortest Path Algorithm** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Dijkstra's Shortest Path Algorithm** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes