Arrays · Matrix Techniques

Matrix In-Place Marking

Using a grid's own first row and column as marker storage to avoid allocating a second grid.

  • 6 min read
  • 11 practice questions
  • 2 graded problems
On this page
  1. Description
  2. The approach
  3. A second flavor: two states in one cell
  4. Where you'll see it
  5. Which tool for which job?
  6. Common mistakes
  7. Check yourself
  8. Key takeaways
  9. Quick revise
  10. Practice

Description

Some grid problems compute a new grid from the old one, where every new value depends on old values elsewhere. The easy fix is a second grid of the same size. This skill does it without one, by borrowing storage the grid already has. Set Matrix Zeroes uses the first row and column as notes. Game of Life uses a spare bit inside each cell. Both need care about when you read a cell and when you write it.

We'll go from simple to more technical:

  1. The pattern: borrow the first row and column as markers, in ordered passes.
  2. A second flavor: keep the current and the next state in the same cell.
  3. Where packing two states into one cell shows up.
  4. The ordering bugs, and when there's no spare room.

The approach

Set Matrix Zeroes: wherever a cell is 0, clear its whole row and column. You can't clear as you go, because a cleared cell looks like an original zero and would clear more. So first write down which rows and columns to clear, then clear them. The notes go in row 0 and column 0. A 0 in matrix[r][0] means "clear row r", and a 0 in matrix[0][c] means "clear column c". Row 0 and column 0 need notes of their own, so save two flags for them before you start.

Here it is on a 3 x 4 grid with zeros at row 0, column 2 and at row 2, column 1. Bold values changed in that pass.

PassRow 0Row 1Row 2
Start1 2 0 45 6 7 89 0 2 3
0: row 0 has a zero, column 0 doesn't1 2 0 45 6 7 89 0 2 3
1: note the zero at row 2, column 11 0 0 45 6 7 80 0 2 3
2: clear inner cells whose row or column is noted1 0 0 45 0 0 80 0 0 0
3: the saved flag clears row 00 0 0 05 0 0 80 0 0 0

The original zero in row 0 already acts as the note for column 2. The flag from pass 0 is what tells pass 3 to clear row 0 itself. Without it, you couldn't tell an original zero in row 0 from a note written there in pass 1.

The four passes in short:

Pass 0: remember whether row 0 / column 0 themselves originally contain a zero.
Pass 1: for every matrix[r][c] == 0 with r, c >= 1, set matrix[r][0] = 0 and matrix[0][c] = 0.
Pass 2: for every r, c >= 1, zero matrix[r][c] if matrix[r][0] == 0 or matrix[0][c] == 0.
Pass 3: apply the saved row-0 / column-0 flags from Pass 0 last.

A second flavor: two states in one cell

Game of Life computes each cell's next state from its neighbors' current states. If you overwrite a cell right away, the cells after it read its new value instead of the old one. There's no idle row to borrow here. But each cell holds only 0 or 1, so the second bit of every int is free. Keep the current state in bit 0 and write the next state into bit 1:

ValueNowNext
0deaddead
1alivedead
2deadalive
3alivealive

Java

// bit 0 = original state (never touched mid-pass), bit 1 = next state
if (nextAlive) board[r][c] |= 2;
// ...only after every cell in the grid has been visited this way:
board[r][c] >>= 1;   // shifts next-state down into bit 0, discarding the original

Python

# bit 0 = original state (never touched mid-pass), bit 1 = next state
if next_alive:
    board[r][c] |= 2
# ...only after every cell in the grid has been visited this way:
board[r][c] >>= 1   # shifts next-state down into bit 0, discarding the original

To read a neighbor's current state, look at bit 0 only: (board[nr][nc] & 1) == 1. A neighbor you've already processed may now hold 3 (alive, staying alive). A plain == 1 check would count it as dead.

Where you'll see it

Simulations and image filters face the same problem: a cell's new value depends on old values around it. Keeping both states in one cell avoids a second copy of a large grid. When memory isn't tight, the second copy is simpler and perfectly fine.

Which tool for which job?

You needUse
Clear rows and columns, O(1) extra spacethe first row and column as markers, plus two flags
The same, when memory doesn't mattertwo boolean arrays (rows, cols) - simpler
Next state from neighbors' current statesbit 0 = now, bit 1 = next; shift at the end
A huge or infinite board that's mostly emptya set of live cells
Fast whole-grid passesloop rows outside, columns inside

Common mistakes

MistakeWhat happensDo this instead
Not recording whether row 0 / column 0 had zeros firstthe marker row wipes itselfsave two flags before pass 1
Zeroing row 0 / column 0 before the restevery cell reads "clear me"apply the inner cells first, the markers last
Checking a neighbor with == 1 after re-encodingupdated neighbors stop countingread the current state with & 1
Marking with a value that can appear in the data (-1)real values get cleareduse the marker rows or spare bits
Looping columns outside, rows insidethe same result, several times slowerrow-major order

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. Why save whether row 0 and column 0 had a zero before pass 1 starts?

Show answer

Pass 1 writes notes into row 0 and column 0. After that, a zero there could be an original zero or a note. The final pass needs to know whether row 0 and column 0 themselves should be cleared, so that has to be read before any note is written.

2. A Game of Life solution writes the next state into bit 1, then checks board[nr][nc] == 1 to see if a neighbor is alive. What's wrong?

Show answer

A neighbor that was alive and stays alive now holds 3, not 1. The == 1 check counts it as dead, so later cells see too few live neighbors. Read only the current-state bit: (board[nr][nc] & 1) == 1.

3. What goes wrong if pass 2 of Set Matrix Zeroes starts before pass 1 has finished?

Show answer

Pass 2 clears cells using an incomplete set of notes. A row or column whose zero pass 1 hasn't reached yet isn't noted, so its cells stay as they are. Find every zero first, then clear.

Key takeaways

  • In-place marking reuses space the grid already has: an idle row and column, or spare bits in each cell.
  • Read every cell's original meaning before any pass starts overwriting it.
  • Set Matrix Zeroes keeps its notes in row 0 and column 0, plus two flags for those two lines.
  • Game of Life keeps the next state in bit 1, reads the current state with & 1, and shifts at the end.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before practice or an interview, and open the full lesson for anything that doesn't ring a bell.

Pick the tool

You needUse
Zero rows and columns, O(1) spacerow 0 / column 0 markers + two flags
The same, simplertwo boolean arrays
Next state from current neighborsbit 0 now, bit 1 next
Unbounded, sparse boarda set of live cells

Snippets worth knowing by heart

Java

boolean row0 = false, col0 = false;
for (int j = 0; j < n; j++) if (m[0][j] == 0) row0 = true;   // 1. read the markers' own data
for (int i = 0; i < r; i++) if (m[i][0] == 0) col0 = true;
for (int i = 1; i < r; i++) for (int j = 1; j < n; j++)
    if (m[i][j] == 0) { m[i][0] = 0; m[0][j] = 0; }           // 2. mark
for (int i = 1; i < r; i++) for (int j = 1; j < n; j++)
    if (m[i][0] == 0 || m[0][j] == 0) m[i][j] = 0;            // 3. inner cells
if (row0) for (int j = 0; j < n; j++) m[0][j] = 0;             // 4. markers last
if (col0) for (int i = 0; i < r; i++) m[i][0] = 0;

Python

for r in range(rows):
    for c in range(cols):
        live = sum(board[i][j] & 1                      # & 1: the current state only
                   for i in range(max(0, r - 1), min(rows, r + 2))
                   for j in range(max(0, c - 1), min(cols, c + 2)) if (i, j) != (r, c))
        if board[r][c] & 1 and live in (2, 3) or not board[r][c] & 1 and live == 3:
            board[r][c] |= 2                            # next state in bit 1
for row in board:
    for c in range(cols):
        row[c] >>= 1                                    # make next the current

The traps

  • Markers not saved first: the marker row wipes itself. Save whether row 0 and column 0 had zeros before pass 1.
  • Markers cleared early: zeroing row 0 first makes every cell read "clear me". Apply the inner cells, then the markers.
  • == 1 after re-encoding: updated neighbors stop counting. Read the current state with & 1.
  • A sentinel that can be real data: marking with -1 clears real values. Use the marker rows or spare bits.
  • Column-major loops: the result is the same but several times slower. Loop rows outside, columns inside.

Staff-level points, one line each

  • Order: save marker flags, mark, apply inner cells, clear markers.
  • Sentinel -1 on [[1, -1], [0, 5]] gave [[0, 0], [0, 0]], not [[0, -1], [0, 0]].
  • == 1 broke a blinker; & 1 didn't.
  • Unbounded boards: a set of live cells - the glider moved by (1, 1) in 4 steps.
  • Row-major was over 3x faster on a 4,000 x 4,000 Java grid.

Say it in an interview

  • "I reuse the first row and column as flags, so it's O(1) extra space."
  • "I record whether they had zeros themselves before I write flags into them."
  • "Each cell keeps its current state in bit 0 and the next in bit 1."
  • "If the board were infinite, I'd keep a set of live cells."

Practice

This skill comes with 11 multiple-choice questions that tell you which misconception a wrong answer reveals and 2 graded problems. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Matrix In-Place Marking free

Set Matrix Zeroes

MediumProCoding problemJava · Python

Wherever a cell of a rows x cols matrix holds 0, wipe out its whole row and its whole column, setting every cell in them to 0. Do it in place.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Game of Life

MediumProCoding problemJava · Python

Given an m x n board where each cell is 0 (dead) or 1 (alive), compute the next state of every cell according to Conway's Game of Life rules, applied simultaneously to the whole board:

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Practice Matrix In-Place Marking free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime