LeetCode Graph Question Summary
Xiahua Liu November 15, 2024 #LeetCode #C++ #AlgorithmData Structure
Graph problems rely heavily on how the data is represented. While there are three standard academic ways, LeetCode focuses primarily on adjacency matrices and adjacency lists.
Adjacency Matrix
This is a 2D array where matrix[i][j] represents an edge from node i to node j.
- Pros: Fast lookups ($O(1)$) to check if an edge exists.
- Cons: Consumes $O(V^2)$ space, which is inefficient for sparse graphs.
- Usage: Best when the number of vertices $V$ is small (e.g., $V \le 1000$).
// Example: unweighted graph
// graph[i][j] = 1 means edge exists, 0 means no edge
vector<vector<int>> ;
Adjacency List
Each vertex maintains a list of the vertices it connects to. This is the most common representation for interview questions.
- Pros: Efficient space complexity $O(V+E)$. Iterating neighbors is fast.
- Cons: Slightly slower lookup to check specific edge existence ($O(\text{degree of } V)$).
LeetCode often provides a flattened list of edges (e.g., [[0,1], [1,2]]). Convert that into an adjacency list first:
// Conversion from edge list to Adjacency List
vector<vector<int>>
Incidence Matrix
Rows represent vertices and columns represent edges. This representation is rarely used in competitive programming or interviews due to complexity and space requirements.
Graph Traversal
Traversing a graph involves visiting nodes while handling potential cycles (unless the graph is guaranteed to be a DAG). We typically use a visited array (or hash set) to track nodes we have already processed.
Depth-First Search (DFS)
DFS goes as deep as possible before backtracking. It is implemented using recursion or an explicit stack.
void
Common use cases:
- Detecting cycles.
- Finding connected components (e.g., "Number of Islands").
- Pathfinding (not necessarily the shortest path).
Breadth-First Search (BFS)
BFS explores neighbors layer by layer and is implemented with a queue.
void
Common use cases:
- Shortest path in unweighted graphs.
- Level-order traversal.
Topological Sorting
Topological sorting is a linear ordering of vertices in a Directed Acyclic Graph (DAG) such that for every edge $u \to v$, $u$ appears before $v$. If the graph contains a cycle, topological sorting is impossible.
Kahn's Algorithm (BFS approach)
Steps:
- Calculate the in-degree (number of incoming edges) for every node.
- Push all nodes with in-degree == 0 into a queue.
- While the queue is not empty:
- Pop a node
uand add it to the sorted result. - For each neighbor
vofu, decrementv's in-degree; if it becomes 0, pushvto the queue.
- Pop a node
- If the result size $\neq$ total nodes, the graph has a cycle.
vector<int>
Classic problem: 207. Course Schedule
Union-Find (Disjoint Set Union)
Union-Find tracks elements partitioned into disjoint sets. It's efficient for detecting cycles in undirected graphs, connecting components (e.g., Kruskal's MST), and "Number of Provinces" problems.
Core operations:
find(x): Returns the representative (root) of the set containingx(path compression).union(x, y): Merges the sets containingxandy(union by rank).
;