Graphs¶
A graph consists of vertices (nodes) and edges. Can be directed/undirected, weighted/unweighted, cyclic/acyclic. Representations: adjacency list (space-efficient, O(V+E)) or adjacency matrix (O(V²), fast lookup). Key algorithms: BFS (shortest path in unweighted), DFS (cycle detection, topological sort), Dijkstra (shortest path weighted), Topological Sort (DAG ordering), Union-Find (connected components).
Key Concepts¶
Deep Dive: Graph Representation
// Adjacency list (most common)
Map<Integer, List<Integer>> graph = new HashMap<>();
graph.computeIfAbsent(0, k -> new ArrayList<>()).add(1);
graph.computeIfAbsent(1, k -> new ArrayList<>()).add(2);
// Or with array of lists
List<List<Integer>> adj = new ArrayList<>();
for (int i = 0; i < n; i++) adj.add(new ArrayList<>());
adj.get(0).add(1); // edge 0 → 1
Deep Dive: BFS & DFS
BFS (shortest path in unweighted graph):
public int bfs(Map<Integer, List<Integer>> graph, int start, int end) {
Queue<Integer> queue = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
queue.offer(start);
visited.add(start);
int level = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int node = queue.poll();
if (node == end) return level;
for (int neighbor : graph.getOrDefault(node, List.of())) {
if (visited.add(neighbor)) queue.offer(neighbor);
}
}
level++;
}
return -1;
}
DFS (cycle detection in directed graph):
// 0 = unvisited, 1 = in progress, 2 = done
public boolean hasCycle(Map<Integer, List<Integer>> graph, int n) {
int[] state = new int[n];
for (int i = 0; i < n; i++) {
if (dfs(graph, i, state)) return true;
}
return false;
}
private boolean dfs(Map<Integer, List<Integer>> graph, int node, int[] state) {
if (state[node] == 1) return true; // Cycle!
if (state[node] == 2) return false;
state[node] = 1;
for (int neighbor : graph.getOrDefault(node, List.of())) {
if (dfs(graph, neighbor, state)) return true;
}
state[node] = 2;
return false;
}
Deep Dive: Topological Sort (Kahn's Algorithm)
Order vertices such that for every edge u→v, u comes before v. Only works on DAGs.
public List<Integer> topologicalSort(int n, int[][] edges) {
List<List<Integer>> adj = new ArrayList<>();
int[] indegree = new int[n];
for (int i = 0; i < n; i++) adj.add(new ArrayList<>());
for (int[] e : edges) {
adj.get(e[0]).add(e[1]);
indegree[e[1]]++;
}
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < n; i++) if (indegree[i] == 0) queue.offer(i);
List<Integer> order = new ArrayList<>();
while (!queue.isEmpty()) {
int node = queue.poll();
order.add(node);
for (int neighbor : adj.get(node)) {
if (--indegree[neighbor] == 0) queue.offer(neighbor);
}
}
return order.size() == n ? order : List.of(); // empty if cycle
}
Deep Dive: Union-Find (Disjoint Set)
class UnionFind {
int[] parent, rank;
UnionFind(int n) {
parent = new int[n]; rank = new int[n];
for (int i = 0; i < n; i++) parent[i] = i;
}
int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]); // Path compression
return parent[x];
}
boolean union(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return false;
if (rank[px] < rank[py]) parent[px] = py;
else if (rank[px] > rank[py]) parent[py] = px;
else { parent[py] = px; rank[px]++; }
return true;
}
}
Common Interview Questions
- Number of Islands (BFS/DFS on grid)
- Clone Graph
- Course Schedule (topological sort)
- Word Ladder (BFS)
- Number of Connected Components (Union-Find)
- Shortest Path in Binary Matrix
- Pacific Atlantic Water Flow