Python 3.11+
The examples use standard Python containers and syntax available in the supported browser runtime; Adjacency List itself is taught as an interview abstraction.
Verify in Python docs(opens in a new tab)Graph representation storing each vertex's neighbors with space proportional to vertices and edges. This guide turns that contract into deliberate Python operations, interview invariants, and a runnable practice loop.
Recognize it when
Consider Adjacency List when the prompt's constraints and required operations match this shape: Graph representation storing each vertex's neighbors with space proportional to vertices and edges.

Sign in to save your code and progress across devices. The lesson and problem statement remain public.
An adjacency list stores, for each vertex, only the neighbors connected by real edges. Its memory tracks graph content instead of every possible vertex pair.
Allocate one neighbor collection for every vertex, including isolated ones. Lists preserve edge order and duplicates; sets enforce unique membership. For an undirected graph, store both directions. Space is O(V + E), counting each undirected edge twice.
Choose direction and duplicate policy before insertion. Independent list allocation matters:
[[]] * node_count aliases all neighbor lists. Sort only if deterministic neighbor order belongs to
the output or traversal contract.
def build_adjacency_list(node_count, edges):
adjacency = [set() for _ in range(node_count)]
for left, right in edges:
adjacency[left].add(right)
adjacency[right].add(left)
return [sorted(neighbors) for neighbors in adjacency]Implement build_adjacency_list(node_count, edges). Deduplicate undirected edges, preserve isolated vertices, and sort neighbors.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
DFS or BFS enumerates only existing edges. With discovery-time visited marking, reachability is O(V + E), unlike scanning a full matrix row for every visited vertex.
def reachable_vertices(adjacency, start):
seen = {start}
stack = [start]
while stack:
node = stack.pop()
for neighbor in adjacency[node]:
if neighbor not in seen:
seen.add(neighbor)
stack.append(neighbor)
return sorted(seen)Implement reachable_vertices(adjacency, start). Return all reachable vertices sorted, using explicit visited state.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
Choose a list for sparse graphs and neighbor iteration. Choose a matrix for dense graphs or many constant-time edge-existence queries. A set-backed list improves duplicate checks but adds hashing cost and loses authored order.
State direction, duplicate policy, and neighbor container. Explain O(V + E) by charging each stored neighbor entry once, then distinguish representation space from traversal space.
Build Graph Representations(opens in a new tab) isolates storage; Course Schedule(opens in a new tab) uses a directed adjacency list for prerequisites.
Python 3.11+
The examples use standard Python containers and syntax available in the supported browser runtime; Adjacency List itself is taught as an interview abstraction.
Verify in Python docs(opens in a new tab)Interview bounds depend on the stated representation, input model, and real Python operations.
| Operation | Average | Worst | Interview note |
|---|---|---|---|
| Core Adjacency List workflow | O(V^2 + E + V log V) | O(V^2 + E + V log V) | Accumulate canonical neighbors in per-node sets while writing symmetric matrix cells, then sort each set for deterministic output. |
O(V^2 + E) for the demonstrated Adjacency List workflow.
These are the mistakes most likely to survive a happy-path example and fail a boundary case.
Placeholder code cannot preserve the Adjacency List invariant or satisfy the public contract.
Prevent it: Implement the smallest complete transition and run the public tests before adding optimizations.
Avoid
def build_graph_representations(node_count, edges):
passUse instead
def build_graph_representations(node_count, edges):
adjacency = [set() for _ in range(node_count)]
matrix = [[0 for _ in range(node_count)] for _ in range(node_count)]
for left, right in edges:
adjacency[left].add(right)
adjacency[right].add(left)
matrix[left][right] = 1
matrix[right][left] = 1
return [[sorted(neighbors) for neighbors in adjacency], matrix]Where you will hit this: Build Graph Representations(opens in a new tab)
Records only the listed edge direction, producing a directed graph instead of the required undirected graph.
Prevent it: Keep this invariant visible while editing: State the precise Adjacency List invariant before coding and preserve it after every update, traversal step, or recursive return.
Avoid
def build_graph_representations(node_count, edges):
adjacency = [[] for _ in range(node_count)]
matrix = [[0] * node_count for _ in range(node_count)]
for left, right in edges:
adjacency[left].append(right)
matrix[left][right] = 1
return [adjacency, matrix]Use instead
def build_graph_representations(node_count, edges):
adjacency = [set() for _ in range(node_count)]
matrix = [[0 for _ in range(node_count)] for _ in range(node_count)]
for left, right in edges:
adjacency[left].add(right)
adjacency[right].add(left)
matrix[left][right] = 1
matrix[right][left] = 1
return [[sorted(neighbors) for neighbors in adjacency], matrix]Where you will hit this: Build Graph Representations(opens in a new tab)
Handle empty state, duplicate values, aliasing, and serialization boundaries explicitly in tests.
Prevent it: Account for every slice, copy, sort, membership test, and container mutation before claiming O(V^2 + E + V log V).
Avoid
def build_graph_representations(node_count, edges):
adjacency = [[] for _ in range(node_count)]
matrix = [[0] * node_count for _ in range(node_count)]
for left, right in edges:
adjacency[left].append(right)
matrix[left][right] = 1
return [adjacency, matrix]Use instead
def build_graph_representations(node_count, edges):
adjacency = [set() for _ in range(node_count)]
matrix = [[0 for _ in range(node_count)] for _ in range(node_count)]
for left, right in edges:
adjacency[left].add(right)
adjacency[right].add(left)
matrix[left][right] = 1
matrix[right][left] = 1
return [[sorted(neighbors) for neighbors in adjacency], matrix]Where you will hit this: Course Schedule(opens in a new tab)
Official Python documentation supports language behavior. Canonical problem pages provide additional practice context.
python-docs · checked 2026-07-27