Design Graph With Shortest Path Calculator - Complete Solution Guide
Design Graph With Shortest Path Calculator is LeetCode problem 2642, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
There is a directed weighted graph that consists of n nodes numbered from 0 to n - 1 . The edges of the graph are initially represented by the given array edges where edges[i] = [from i , to i , edgeCost i ] meaning that there is an edge from from i to to i with the cost edgeCost i . Implement the Graph class: Graph(int n, int[][] edges) initializes the object with n nodes and the given edges. addEdge(int[] edge) adds an edge to the list of edges where edge = [from, to, edgeCost] . It is guarant
Detailed Explanation
The problem requires designing a `Graph` class that supports finding the shortest path between two nodes in a directed, weighted graph. The graph is initialized with a given number of nodes and a set of edges. The class must support adding new edges to the graph and querying the shortest path between any two nodes. If no path exists between two nodes, the `shortestPath` method should return -1.
Solution Approach
The solution utilizes Dijkstra's algorithm to compute the shortest path between two nodes in the graph. The graph is represented using an adjacency list, where each node maintains a list of its neighbors and the cost to reach them. A priority queue is used to store nodes based on their distance from the starting node, ensuring that the node with the smallest distance is processed first. The `shortestPath` method iteratively expands the search from the starting node until the destination node is reached or all reachable nodes have been explored. When a new edge is added using `addEdge`, it's simply appended to the adjacency list of the source node.
Step-by-Step Algorithm
- Step 1: Initialize the `Graph` with the given number of nodes and edges. Create an adjacency list to represent the graph. Each element of the adjacency list represents a node, and each node contains a list of its neighbors (nodes it has a direct edge to) and the cost of traversing that edge.
- Step 2: Implement the `addEdge` method to add a new edge to the graph. This involves adding the destination node and its corresponding cost to the adjacency list of the source node.
- Step 3: Implement the `shortestPath` method. This method uses Dijkstra's algorithm.
- Step 4: Create a `distances` array to store the shortest distance from the starting node (`node1`) to each node in the graph. Initialize all distances to infinity, except for the starting node, which is initialized to 0.
- Step 5: Create a priority queue `pq` to store nodes to visit. Add the starting node with a distance of 0 to the priority queue.
- Step 6: While the priority queue is not empty, extract the node `u` with the smallest distance from the priority queue. If the distance to `u` is greater than the current shortest distance to `u` (stored in `distances[u]`), then skip this node (this handles cases where the priority queue contains outdated distance values).
- Step 7: If `u` is the destination node (`node2`), return the shortest distance to `u` (which is stored in `distances[u]`).
- Step 8: Iterate through all the neighbors `v` of `u`. For each neighbor `v`, calculate the distance from the starting node to `v` through `u`. If this distance is smaller than the current shortest distance to `v` (stored in `distances[v]`), update `distances[v]` and add `v` to the priority queue with the updated distance.
- Step 9: If the destination node is not reached after processing all reachable nodes, return -1, indicating that there is no path from the starting node to the destination node.
Key Insights
- Insight 1: Dijkstra's algorithm is the most suitable for finding the shortest path in a weighted graph efficiently, especially when we might add edges later.
- Insight 2: Using a priority queue (min-heap) allows us to efficiently select the node with the smallest distance from the source during the Dijkstra's algorithm, which optimizes the search process.
- Insight 3: Representing the graph using an adjacency list is beneficial for both adding edges and finding neighbors of a node, especially when the graph might be sparse (not all nodes are connected to each other).
Complexity Analysis
Time Complexity: O(E * log(V))
Space Complexity: O(V + E)
Topics
This problem involves: Graph, Design, Heap (Priority Queue), Shortest Path.
Companies
Asked at: Nike, Samsung.