Bird
Raised Fist0
DSA Javaprogramming

Dijkstra's Algorithm Single Source Shortest Path in DSA Java

Choose your learning style10 modes available
Mental Model
Find the shortest path from one starting point to all other points by always choosing the closest unvisited point next.
Analogy: Imagine you are in a city and want to find the shortest way to every other place. You start from your home and always visit the nearest new place you haven't been to yet, updating the shortest known routes as you go.
Graph nodes with distances:

  (A)
 /   \
5     2
/       \
(B)---1--(C)

Start at A with distance 0, others unknown (∞).
Dry Run Walkthrough
Input: Graph with nodes A, B, C and edges: A-B=5, A-C=2, B-C=1; start at A
Goal: Find shortest distances from A to all nodes
Step 1: Start at A, set distance to A=0, others ∞
Distances: A=0, B=∞, C=∞; Visited: none
Why: We know distance to start is zero, others unknown
Step 2: Visit nearest unvisited node: C (distance 2)
Distances: A=0, B=5, C=2; Visited: A
Why: C is closest to A, so we explore paths from C next
Step 3: Update distance to B via C: min(5, 2+1)=3
Distances: A=0, B=3, C=2; Visited: A, C
Why: Going A->C->B is shorter than previous 5
Step 4: Visit next nearest unvisited node: B (distance 3)
Distances: A=0, B=3, C=2; Visited: A, C, B
Why: B is now the closest unvisited node
Step 5: All nodes visited, shortest distances found
Distances: A=0, B=3, C=2; Visited: A, B, C
Why: Algorithm ends when all nodes are visited
Result:
Shortest distances from A: A=0 -> B=3 -> C=2
Annotated Code
DSA Java
import java.util.*;

class Graph {
    private final Map<String, List<Edge>> adj = new HashMap<>();

    static class Edge {
        String target;
        int weight;
        Edge(String target, int weight) {
            this.target = target;
            this.weight = weight;
        }
    }

    void addEdge(String source, String target, int weight) {
        adj.computeIfAbsent(source, k -> new ArrayList<>()).add(new Edge(target, weight));
        adj.computeIfAbsent(target, k -> new ArrayList<>()); // Ensure target node exists
    }

    Map<String, Integer> dijkstra(String start) {
        Map<String, Integer> dist = new HashMap<>();
        for (String node : adj.keySet()) {
            dist.put(node, Integer.MAX_VALUE);
        }
        dist.put(start, 0);

        PriorityQueue<Map.Entry<String, Integer>> pq = new PriorityQueue<>(Comparator.comparingInt(Map.Entry::getValue));
        pq.offer(new AbstractMap.SimpleEntry<>(start, 0));

        Set<String> visited = new HashSet<>();

        while (!pq.isEmpty()) {
            Map.Entry<String, Integer> current = pq.poll();
            String currNode = current.getKey();
            if (visited.contains(currNode)) continue;
            visited.add(currNode);

            for (Edge edge : adj.get(currNode)) {
                if (visited.contains(edge.target)) continue;
                int newDist = dist.get(currNode) + edge.weight;
                if (newDist < dist.get(edge.target)) {
                    dist.put(edge.target, newDist);
                    pq.offer(new AbstractMap.SimpleEntry<>(edge.target, newDist));
                }
            }
        }
        return dist;
    }
}

public class DijkstraDemo {
    public static void main(String[] args) {
        Graph g = new Graph();
        g.addEdge("A", "B", 5);
        g.addEdge("A", "C", 2);
        g.addEdge("B", "C", 1);

        Map<String, Integer> distances = g.dijkstra("A");
        for (String node : distances.keySet()) {
            System.out.println("Distance from A to " + node + " = " + distances.get(node));
        }
    }
}
dist.put(start, 0);
Initialize start node distance to zero
pq.offer(new AbstractMap.SimpleEntry<>(start, 0));
Add start node to priority queue with distance zero
Map.Entry<String, Integer> current = pq.poll();
Extract node with smallest distance from queue
if (visited.contains(currNode)) continue;
Skip nodes already processed
visited.add(currNode);
Mark current node as visited
for (Edge edge : adj.get(currNode)) {
Check all neighbors of current node
int newDist = dist.get(currNode) + edge.weight;
Calculate new possible distance to neighbor
if (newDist < dist.get(edge.target)) {
If new distance is shorter, update it
dist.put(edge.target, newDist);
Update shortest distance to neighbor
pq.offer(new AbstractMap.SimpleEntry<>(edge.target, newDist));
Add neighbor to queue with updated distance
OutputSuccess
Distance from A to A = 0 Distance from A to B = 3 Distance from A to C = 2
Complexity Analysis
Time: O(E log V) because each edge is checked and priority queue operations take log V time
Space: O(V + E) to store graph and distance data
vs Alternative: Compared to Bellman-Ford's O(VE), Dijkstra is faster on graphs without negative edges
Edge Cases
Graph with isolated nodes (no edges)
Distances to isolated nodes remain infinite (unreachable)
DSA Java
dist.put(start, 0);
Graph with single node
Distance to start node is zero, no other nodes to process
DSA Java
dist.put(start, 0);
Graph with multiple edges between same nodes
Algorithm picks shortest edge automatically by updating distances
DSA Java
if (newDist < dist.get(edge.target)) {
When to Use This Pattern
When you need shortest paths from one point to all others in a graph with non-negative weights, use Dijkstra's algorithm because it efficiently finds minimum distances.
Common Mistakes
Mistake: Not marking nodes as visited and revisiting them endlessly
Fix: Add a visited set and skip nodes already processed
Mistake: Using a normal queue instead of a priority queue
Fix: Use a priority queue to always pick the closest unvisited node
Mistake: Not updating distances when a shorter path is found
Fix: Check and update distances only if new path is shorter
Summary
Finds shortest distances from one start node to all others in a weighted graph.
Use when you want efficient shortest paths and all edge weights are non-negative.
Always pick the closest unvisited node next and update neighbors' distances.

Practice

(1/5)
1. What is the main purpose of Dijkstra's Algorithm in graph theory?
easy
A. To find the shortest path from a single source to all other vertices
B. To find the maximum flow in a network
C. To detect cycles in a graph
D. To sort vertices in topological order

Solution

  1. Step 1: Understand the algorithm's goal

    Dijkstra's Algorithm is designed to find the shortest distance from one starting point (source) to every other point in a graph with non-negative edge weights.
  2. Step 2: Compare with other graph algorithms

    Other algorithms like max flow or cycle detection serve different purposes, so they do not match Dijkstra's goal.
  3. Final Answer:

    To find the shortest path from a single source to all other vertices -> Option A
  4. Quick Check:

    Dijkstra's Algorithm = shortest paths from source [OK]
Hint: Dijkstra finds shortest paths from one start point [OK]
Common Mistakes:
  • Confusing with max flow algorithms
  • Thinking it detects cycles
  • Mixing with topological sort
2. Which Java data structure is commonly used to efficiently select the next vertex with the smallest tentative distance in Dijkstra's Algorithm?
easy
A. HashMap
B. ArrayList
C. PriorityQueue
D. LinkedList

Solution

  1. Step 1: Identify the need for efficient minimum selection

    Dijkstra's Algorithm repeatedly picks the vertex with the smallest current distance. A data structure that supports quick extraction of the minimum element is needed.
  2. Step 2: Match data structures to this need

    PriorityQueue in Java supports efficient retrieval of the smallest element, unlike ArrayList or LinkedList which require scanning all elements.
  3. Final Answer:

    PriorityQueue -> Option C
  4. Quick Check:

    PriorityQueue = efficient min extraction [OK]
Hint: Use PriorityQueue to get smallest distance vertex fast [OK]
Common Mistakes:
  • Using ArrayList which is slow for min extraction
  • Choosing HashMap which stores key-value pairs but not order
  • Using LinkedList which is inefficient for min selection
3. What will be the output distances array after running Dijkstra's Algorithm from source vertex 0 on this graph?
int[][] graph = {
  {0, 4, 0, 0, 0, 0, 0, 8, 0},
  {4, 0, 8, 0, 0, 0, 0, 11, 0},
  {0, 8, 0, 7, 0, 4, 0, 0, 2},
  {0, 0, 7, 0, 9, 14, 0, 0, 0},
  {0, 0, 0, 9, 0, 10, 0, 0, 0},
  {0, 0, 4, 14, 10, 0, 2, 0, 0},
  {0, 0, 0, 0, 0, 2, 0, 1, 6},
  {8, 11, 0, 0, 0, 0, 1, 0, 7},
  {0, 0, 2, 0, 0, 0, 6, 7, 0}
};
medium
A. [0, 4, 12, 19, 21, 11, 9, 8, 14]
B. [0, 4, 8, 15, 20, 11, 9, 8, 10]
C. [0, 4, 7, 14, 19, 9, 8, 7, 13]
D. [0, 5, 10, 17, 22, 12, 11, 9, 15]

Solution

  1. Step 1: Initialize distances and process vertices

    Start with distance 0 for vertex 0 and infinity for others. Update neighbors step-by-step using the graph edges and weights.
  2. Step 2: Calculate shortest distances

    Following Dijkstra's logic, the shortest distances from vertex 0 to others are: 0 (self), 4, 12, 19, 21, 11, 9, 8, 14.
  3. Final Answer:

    [0, 4, 12, 19, 21, 11, 9, 8, 14] -> Option A
  4. Quick Check:

    Distances array matches [0, 4, 12, 19, 21, 11, 9, 8, 14] [OK]
Hint: Trace updates from source, pick smallest tentative distances [OK]
Common Mistakes:
  • Mixing up edge weights during updates
  • Not updating distances after finding shorter paths
  • Confusing vertex indices
4. Identify the error in this Java snippet implementing Dijkstra's Algorithm:
for (int i = 0; i < graph.length; i++) {
  int u = pq.poll();
  for (int v = 0; v < graph.length; v++) {
    if (graph[u][v] != 0 && dist[u] + graph[u][v] < dist[v]) {
      dist[v] = dist[u] + graph[u][v];
      pq.add(v);
    }
  }
}
medium
A. PriorityQueue should store distances, not vertices
B. dist array is not initialized before the loop
C. The inner loop should start from 1, not 0
D. Vertices are added to PriorityQueue without updating their priority

Solution

  1. Step 1: Understand PriorityQueue usage

    The PriorityQueue must order vertices by their current shortest distance. Adding vertices without updating their priority causes incorrect ordering.
  2. Step 2: Identify missing priority update

    When a shorter path is found, the vertex's priority in the queue must be updated or reinserted properly to reflect new distance.
  3. Final Answer:

    Vertices are added to PriorityQueue without updating their priority -> Option D
  4. Quick Check:

    PriorityQueue must reflect updated distances [OK]
Hint: Update priority in queue when distances change [OK]
Common Mistakes:
  • Ignoring priority updates in PriorityQueue
  • Starting loop incorrectly from 1
  • Not initializing distance array
5. Given a weighted graph with some edges having zero weight, how does Dijkstra's Algorithm behave, and what modification is needed to correctly find shortest paths?
hard
A. It works normally; no modification needed
B. It may fail due to zero-weight cycles; use Bellman-Ford instead
C. It requires ignoring zero-weight edges to avoid infinite loops
D. It requires initializing distances to zero for all vertices

Solution

  1. Step 1: Recall Dijkstra's requirements

    Dijkstra's Algorithm works correctly on graphs with non-negative edge weights, but zero-weight cycles can cause infinite loops or incorrect behavior.
  2. Step 2: Impact of zero weights

    Zero-weight edges and zero-weight cycles may cause the algorithm to revisit vertices indefinitely. Bellman-Ford algorithm handles such cases correctly.
  3. Final Answer:

    It may fail due to zero-weight cycles; use Bellman-Ford instead -> Option B
  4. Quick Check:

    Bellman-Ford handles zero-weight cycles correctly [OK]
Hint: Use Bellman-Ford if zero-weight cycles exist [OK]
Common Mistakes:
  • Confusing zero weights with negative weights
  • Thinking zero cycles cause infinite loops
  • Believing Bellman-Ford needed for zeros
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard