
Matrix (2D array) problems are a very common category in algorithmic problem solving and competitive programming.
They primarily focus on:
Unlike patterns such as Sliding Window or Kadane’s Algorithm, matrix problems
rarely introduce complex algorithmic optimizations.
Instead, they emphasize precision, correctness, and a clear mental model of how the grid is traversed and updated.
Once the main traversal or transformation pattern is identified, the solution is usually straightforward to implement and runs in linear time with respect to the number of cells.
Most matrix problems are not about complex algorithms, but about how you move inside the grid.
Understanding traversal patterns is the key to solving 2D array exercises correctly and cleanly.
The simplest pattern scans the matrix row by row, from left to right.
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
// process matrix[r][c]
}
}
This traversal is commonly used when:
This pattern scans the matrix column by column, from top to bottom.
for (let c = 0; c < cols; c++) {
for (let r = 0; r < rows; r++) {
// process matrix[r][c]
}
}
It is useful when:
Directional traversal moves through the matrix following a specific direction. It is often used as a building block for more complex patterns.
/// left to right
for (let c = left; c <= right; c++) {
// process matrix[top][c]
}
/// top to bottom
for (let r = top; r <= bottom; r++) {
// process matrix[r][right]
}
/// right to left
for (let c = right; c >= left; c--) {
// process matrix[bottom][c]
}
/// bottom to top
for (let r = bottom; r >= top; r--) {
// process matrix[r][left]
}
Spiral traversal processes the matrix layer by layer, shrinking its boundaries after each full cycle.
let top = 0;
let bottom = rows - 1;
let left = 0;
let right = cols - 1;
while (top <= bottom && left <= right) {
// left → right
for (let c = left; c <= right; c++) {
// process matrix[top][c]
}
top++;
// top → bottom
for (let r = top; r <= bottom; r++) {
// process matrix[r][right]
}
right--;
if (top <= bottom) {
// right → left
for (let c = right; c >= left; c--) {
// process matrix[bottom][c]
}
bottom--;
}
if (left <= right) {
// bottom → top
for (let r = bottom; r >= top; r--) {
// process matrix[r][left]
}
left++;
}
}
Some problems require updating the matrix over multiple steps rather than producing a single traversal order.
Typical characteristics:
Matrix problems are usually bounded by the size of the grid itself.
In most cases, the complexity is dictated by how many times each cell is visited.
Below is a summary of the most common patterns and their complexities.
| Pattern / Operation | Time Complexity | Space Complexity |
|---|---|---|
| Full matrix traversal | ||
| Row-wise / column-wise scan | ||
| Spiral traversal | ||
| In-place matrix rotation | ||
| Validation (rows + cols + boxes) | ||
| Simulation with temporary state |
It is important to note that:
Understanding these constraints helps focus on correct traversal and boundary handling, rather than over-optimizing time complexity.
| Problem | Technique | Solution |
|---|---|---|
| Spiral Matrix | Directional traversal + boundary shrink | Solution |
| Rotate Image | In-place transpose + row reversal | Solution |
| Set Matrix Zeroes | In-place markers (first row/column) | Solution |
| Valid Sudoku | Constraint validation (rows, columns, boxes) | Solution |
| Game of Life | In-place state encoding / simulation | Solution |