Foundations
2D Arrays (Matrices)
Fundamentals · Core
Level: CoreMatrix Traversal
Complexity
| Operation | Time |
|---|---|
| Read or write a cell | O(1) |
| Visit every cell | O(rows × cols) |
| Transpose or rotate | O(rows × cols) |
| Search in a sorted matrix | O(rows + cols) with the staircase method |
A matrix is an array of rows, grid[row][col]. Grids model boards, maps, images and dynamic programming tables, so grid traversal is one of the most reused skills.
Basics
const rows = grid.length;
const cols = grid[0].length;
const value = grid[r][c];Create one correctly. Array(rows).fill(Array(cols).fill(0)) reuses the same row for every index.
const grid = Array.from({ length: rows }, () => Array(cols).fill(0));Moving around
Store the four directions once and loop over them. Check bounds before reading.
const DIRS = [[1, 0], [-1, 0], [0, 1], [0, -1]];
for (const [dr, dc] of DIRS) {
const nr = r + dr, nc = c + dc;
if (nr < 0 || nc < 0 || nr >= rows || nc >= cols) continue;
// use grid[nr][nc]
}Add the four diagonals for 8-direction movement.
Handy facts
- Cells on the same diagonal share
r - c. Cells on the same anti-diagonal sharer + c. - A flat index and a cell convert with
i = r * cols + c,r = Math.floor(i / cols),c = i % cols. - Transpose swaps
grid[r][c]withgrid[c][r]. Rotating 90 degrees clockwise is a transpose then reversing each row.
Common patterns
- Flood fill, islands, regions: DFS or BFS from a cell (see Matrix Traversal pattern).
- Shortest path in a maze: BFS.
- Spiral and rotation: track four boundaries and shrink them.
- Grid DP:
dp[r][c]fromdp[r-1][c]anddp[r][c-1](unique paths, minimum path sum).
Common mistakes
- Shared rows from
fill(see above). - Mixing up
rowsandcols, orgrid[x][y]againstgrid[y][x]. - Mutating the grid to mark visited and then needing the original.
Code
export const createGrid = (rows, cols, fill = 0) => Array.from({ length: rows }, () => Array(cols).fill(fill));
export const transpose = m => m[0].map((_, c) => m.map(row => row[c]));
export const rotateClockwise = m => transpose(m).map(row => row.reverse());
export function spiral(m) {
const out = [];
let top = 0, bottom = m.length - 1, left = 0, right = m[0].length - 1;
while (top <= bottom && left <= right) {
for (let c = left; c <= right; c++) out.push(m[top][c]);
top++;
for (let r = top; r <= bottom; r++) out.push(m[r][right]);
right--;
if (top <= bottom) { for (let c = right; c >= left; c--) out.push(m[bottom][c]); bottom--; }
if (left <= right) { for (let r = bottom; r >= top; r--) out.push(m[r][left]); left++; }
}
return out;
}
const DIRS = [[1, 0], [-1, 0], [0, 1], [0, -1]];
export function countIslands(grid) { // grid of '1' (land) and '0'
let count = 0;
const sink = (r, c) => {
if (grid[r]?.[c] !== '1') return;
grid[r][c] = '0';
for (const [dr, dc] of DIRS) sink(r + dr, c + dc);
};
grid.forEach((row, r) => row.forEach((v, c) => { if (v === '1') { count++; sink(r, c); } }));
return count;
}Practice
Matrix Traversal
- Flood FillEasy
- Island PerimeterEasy
- Transpose MatrixEasy
- Toeplitz MatrixEasy
- Number of IslandsMedium
- Max Area of IslandMedium
- Surrounded RegionsMedium
- Spiral MatrixMedium
- Rotate ImageMedium
- Set Matrix ZeroesMedium
- Game of LifeMedium
- Word SearchMedium
- Number of EnclavesMedium
- Spiral Matrix IIMedium
- Diagonal TraverseMedium
- Search a 2D Matrix IIMedium
- Longest Increasing Path in a MatrixHard
- Word Search IIHard
Spotted a mistake or something unclear? Report it on GitHub.