Leetcode is Easy! Graph Patterns.
By: Tim Park
Tags: Coding Interviews, Python, Leetcode Is Easy, Algorithms

Before we start, I want to emphasize that the goal of this article is not to teach you how to solve graph patterns. Instead, I will simply be showing you that these subpatterns within graph patterns exist.

Graph problems are a crucial topic that you’ll need to master for technical interviewing. When you read about graphs, articles usually focus on the following:

Representation — Adjacency List vs. Adjacency Matrix Traversals — BFS vs. DFS

These are core concepts but we need to recognize the different variations that these graph problems ask. Each variation appears to be the same on a surface level (it’s a graph and we need to traverse) but each variation requires a unique approach to solve the problem correctly.

Pattern 1: Edge List

Many graph problems provide us an edge list as an input. If we are looking for the number of connected components, run a union-find on the edge list and we’re done.

If we need to do literally anything else, convert it to an adjacency list. Think about the tradeoff between representing the graph as an adjacency list (O(V+E) traversal time and space) vs. adjacency matrix (O(V²) time and space). If the graph is dense, the matrix is fine. Graphs are usually large and sparse so we opt for the adjacency list.

# EDGE LIST TO ADJ LIST get_adj_list(edges):

temp = collections.defaultdict(list)

for x, y in edges:

temp[x].append(y) # Adjacency list for a directed graph

return temp

Pattern 2: Adjacency List

So once we’ve converted our edge list to an adjacency list, we arrive at pattern 2. There are a few subpatterns within the adjacency list pattern.

Is there a Path? BFS/DFS Shortest Path w/ Unweighted Edges? BFS Shortest Path w/ Weighted Edges? BFS w/ Max Heap Ordering the nodes? Topological Sort Detecting a cycle? Topological Sort or BFS/DFS

I won’t go into the “how to solve” because each would require it’s own article, but it’s a huge step in itself to realize that these are all distinct problems.

Internalize the difference and practice the variations.

Pattern 3: Grid

My personal favorite type of graph problem is the implicit graph given to us as a grid. Nodes are represented as a (row, col) cell in the grid, and edges are represented by any touching left, right, up, and down neighbors.

# GRID 0 1 2

0 0 1 1

1 0 0 0

2 1 0 0

With grid problems, we’ll need to think about the following:

Traversing the grid by iterating over the rows and columns Using a visited set so we don’t enter an infinite loop Directional Moves to traverse left, right, up, and down Is the move we’re trying to make in bounds of the grid?

Again, explaining how to solve this pattern would require its own article so I’ll leave it at a high-level overview.

My goal is to simply help you to separate this type of graph problem from all the other graph problems previously discussed.

Pattern 4: Adjacency Matrix

The last pattern is an adjacency matrix and is not that common, so I’ll keep this section short.

The key here is to remember to iterate over the rows and the columns using Python’s enumerate. The index of the row will represent node_1 and the index of the column will represent node_2. The value at the matrix[row][col] will tell us whether or not there is an edge connecting these two nodes.

#ADJACENCY MATRIX 0 1 2 3

0 0 1 0 0

1 0 0 0 0

2 0 1 0 0

3 1 0 0 0 Here there is an edge between: (0) -> (1), (2) -> (1), (3) -> (0)

Conclusion

I know you’re thinking, “What? He didn’t even teach us how to solve anything”.

That wasn’t the point.

The true point of this article was to get you through to that “aha” moment of realization, where you realize there are subpatterns within patterns of graph problems.

This realization took me way too long to learn. I didn’t recognize this so I would keep trying to fit adjacency list traversal steps into a grid traversal problem. This is confusing and will most likely be wrong.

By learning how to solve these graph patterns independently of each other, you’ll be able to keep your head straight during a high-pressure interview.