Skip to content

Beginner: foundations · Arrays and strings · topic 10 of 61 · 40 min

2-D arrays (matrices)

Explanation

A matrix is a grid of rows and columns, stored in Python as a list of lists: grid[row][col]. You walk it row by row, swap rows and columns to transpose it, rotate it 90° clockwise with a transpose plus reversing rows, and read it in spiral order with four shrinking boundaries. A matrix sorted along rows and columns can be searched in O(m + n) from the top-right corner.

Rows and columns

A 2-D array, or matrix, is a grid. Rows run across, columns run down. A grid with m rows and n columns has m × n cells. In Python it is a list of rows, and each row is a list, so grid[r][c] is the cell in row r and column c. len(grid) is the number of rows and len(grid[0]) is the number of columns (when there is at least one row).

Think of it like this: A cinema hall: rows A, B, C … and seat numbers 1, 2, 3 … in each row. "Row C, seat 7" is grid[2][6] when you count from 0. Booking apps keep exactly such a grid of free and taken seats.
Careful: Never create a grid with [[0] * n] * m. It makes m references to the SAME row, so changing one cell changes that column in every row. Use [[0] * n for _ in range(m)] instead.
python
bad = [[0] * 3] * 2
bad[0][0] = 1
print(bad)    # Output: [[1, 0, 0], [1, 0, 0]]

good = [[0] * 3 for _ in range(2)]
good[0][0] = 1
print(good)   # Output: [[1, 0, 0], [0, 0, 0]]

Row-major traversal and neighbours

Row-major order means reading the grid row by row, left to right, like reading a page. It is the natural nested loop: for r in range(m), then for c in range(n). Visiting every cell is O(m × n). Many grid problems also look at the four neighbours of a cell (up, down, left, right); always check that r and c stay inside 0..m − 1 and 0..n − 1 before reading.

python
grid = [[1, 2, 3],
        [4, 5, 6]]
for r in range(len(grid)):
    for c in range(len(grid[0])):
        print(grid[r][c], end=" ")
# Output: 1 2 3 4 5 6

DIRS = [(-1, 0), (1, 0), (0, -1), (0, 1)]   # up, down, left, right

Transpose

Transposing swaps rows and columns: the cell at (r, c) moves to (c, r). An m × n matrix becomes n × m, so a non-square matrix needs a NEW grid. zip(*grid) is a Python shortcut that groups the first items of every row, then the second items, and so on; it gives tuples, so convert each to a list.

python
grid = [[1, 2, 3],
        [4, 5, 6]]
t = [list(col) for col in zip(*grid)]
print(t)   # Output: [[1, 4], [2, 5], [3, 6]]

Rotate 90° clockwise

A clockwise rotation is a transpose followed by reversing each row. For a square n × n matrix both steps can be done in place (swap grid[r][c] with grid[c][r] for c > r, then reverse each row), O(n²) time and O(1) extra space. For a non-square matrix, build a new grid: rotated row c is column c read from bottom to top.

python
grid = [[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]]
rotated = [list(row) for row in zip(*grid[::-1])]
print(rotated)   # Output: [[7, 4, 1], [8, 5, 2], [9, 6, 3]]
grid[::-1] flips the rows upside down; zip then reads columns. Same result as transpose + reverse each row.

Spiral order

Spiral order reads the outer ring clockwise (top row, right column, bottom row, left column), then the next ring inside, and so on. Keep four boundaries: top, bottom, left and right. After reading the top row, move top down; after the right column, move right left; and so on. Before reading the bottom row and left column, check that top ≤ bottom and left ≤ right again, otherwise a single row or column is read twice. O(m × n) time.

Searching a sorted matrix

If every row is sorted left to right and every column is sorted top to bottom, start at the top-right corner. If the value there is bigger than the target, the whole column below is even bigger, so move left. If it is smaller, the whole row to the left is even smaller, so move down. Each step removes a row or a column, so the search takes at most m + n steps: O(m + n) time and O(1) space. This is called the staircase search.

Grids as maps

Many problems hide a grid: a cinema seat map, a chessboard of 8 × 8 squares, a maze where "#" is a wall, or pixels of an image. Counting islands of land or finding the shortest path through a maze is grid traversal with BFS or DFS, which you will learn in Module 9.

Common mistakes

  • Creating rows with [[0] * n] * m, which shares one row. Fix: use a list comprehension.
  • Mixing up rows and columns, for example grid[x][y] with x as the column. Fix: always name them r and c and write grid[r][c].
  • Assuming the matrix is square. Fix: use m = len(grid) and n = len(grid[0]) separately, and test a 2 × 3 case.
  • Crashing on [] or [[]]. Fix: check if not grid or not grid[0] first.
  • Reading a single middle row or column twice in spiral order. Fix: re-check the boundaries before the bottom row and the left column.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

2-D arrays (matrices) · 1/8

2-D arrays

This lesson is about matrices: grids of rows and columns, and the classic interview moves on them.

Prefer a video by a teacher? Find free videos on “matrix spiral order rotate image 90 degrees search 2d matrix interview” on YouTube ↗

In real life: A cinema seat map

Movie booking apps show the hall as a grid: each row is a list of seats, marked free or taken. To suggest "best available" seats, the app scans rows near the middle of the screen and looks for a run of free neighbouring seats in the same row. That is row-major traversal plus a simple run count, the same skills as in this lesson.

python
hall = [
    [1, 1, 0, 0, 0, 1],
    [0, 0, 1, 0, 0, 0],
    [1, 0, 0, 0, 1, 1],
]   # 1 = taken, 0 = free
need = 3
for r, row in enumerate(hall):
    run = 0
    for c, seat in enumerate(row):
        run = run + 1 if seat == 0 else 0
        if run == need:
            print("Row", "ABC"[r], "seats", c - need + 2, "to", c + 1)
            break
Shows Row A seats 3 to 5, Row B seats 4 to 6 and Row C seats 2 to 4 (seat numbers start at 1).

Practice (0/4 done)

Task 1 · Code · Python

Write transpose(matrix) that returns a NEW matrix with rows and columns swapped, so the result has len(matrix[0]) rows. It must work for non-square matrices. If matrix is [] or [[]], return []. Example: transpose([[1, 2, 3], [4, 5, 6]]) returns [[1, 4], [2, 5], [3, 6]].

Task 2 · Code · Python

Write rotate_clockwise(matrix) that returns a NEW matrix rotated 90° clockwise. It must work for non-square matrices (an m × n input gives an n × m result). Return [] for []. Example: rotate_clockwise([[1, 2], [3, 4]]) returns [[3, 1], [4, 2]].

Task 3 · Code · Python

Write spiral_order(matrix) that returns all values in clockwise spiral order, starting at the top-left: across the top row, down the right column, back along the bottom row, up the left column, then the next ring inside. Return [] for [] or [[]]. Example: spiral_order([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) returns [1, 2, 3, 6, 9, 8, 7, 4, 5].

Task 4 · Code · Python

Each row of matrix is sorted in non-decreasing order left to right, and each column top to bottom. Write search_matrix(matrix, target) that returns True if target is in the matrix, else False, in O(m + n) time using the staircase search from the top-right corner. Return False for [] or [[]].

Quick quiz

Question 1

1.grid has 3 rows and 5 columns. What is len(grid[0])?

Question 2

2.Why is [[0] * 4] * 3 a bad way to build a 3 × 4 grid?

Question 3

3.Which steps rotate a square matrix 90° clockwise?

Question 4

4.Staircase search starts at the top-right and the value there is bigger than the target. What next?

Question 5

5.What is the time of staircase search on an m × n matrix?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

grid has 3 rows and 5 columns. What is len(grid[0])?

Answer: 5

grid[0] is the first row, which holds one value per column.

Why is [[0] * 4] * 3 a bad way to build a 3 × 4 grid?

Answer: All three rows are the same list, so a change in one shows in all

Multiplying the outer list copies references to one row. Use a list comprehension.

Which steps rotate a square matrix 90° clockwise?

Answer: Transpose, then reverse each row

Transpose then reverse each row gives clockwise. (Reverse rows order then transpose is the same result.)

Staircase search starts at the top-right and the value there is bigger than the target. What next?

Answer: Move left

Everything below in that column is even bigger, so that column can be dropped.

What is the time of staircase search on an m × n matrix?

Answer: O(m + n)

Each step removes one row or one column, so at most m + n steps.

In a function parameter for a 2D int array with 4 columns, which is valid?Related

Answer: int g[][4]

All dimensions except the first are required.

From 2D arrays and classic array algorithms

Linear search on 1,000 items needs at most how many comparisons?Related

Answer: 1,000

It may check every element.

From Two-dimensional arrays and array algorithms

In "unique paths" (moves right or down only), where can the paths into cell (r, c) come from?Related

Answer: From the cell above and the cell to the left

With only right and down moves, the last step into (r, c) was down from (r − 1, c) or right from (r, c − 1).

From 2-D DP on grids and strings

Rotating a list of 5 items right by 12 is the same as rotating by…Related

Answer: 2

12 % 5 = 2. Every full 5 rotations bring the list back to where it started.

From Arrays: traversal and in-place updates

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. This is the last topic of “Arrays and strings”. The module exam comes next.
  2. Module 2 exam: Arrays and strings · 14 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Hashing, two pointers and sliding window. 61 topics left in the course before the final exam.

← Previous: Maximum subarray: Kadane's algorithm