Game of Life

MediumMatrix · Simulation · In-place State Encoding🧩 Matrix TraversalLeetCode #289 ↗Updated

Problem

An m x n grid board holds cells that are alive (1) or dead (0). Advance it by one generation, where every cell looks at its 8 neighbours at the same moment: a live cell survives only with 2 or 3 live neighbours, and a dead cell comes alive with exactly 3. Update board in-place.
Input[[0,1,0],[0,0,1],[1,1,1],[0,0,0]]Output[[0,0,0],[1,0,1],[0,1,1],[0,1,0]]
Input[[1,1],[1,0]]Output[[1,1],[1,1]]

1 ≤ m, n ≤ 25  ·  board[i][j] is 0 or 1  ·  Follow-up: solve it in-place with O(1) extra memory.

Try it yourself

Java
class Solution {
    public void gameOfLife(int[][] board) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Each cell needs only 1 bit today but an int has 32. Store the next state in bit 1 while bit 0 keeps the current state, so neighbours still read the old value with & 1; finish with one >> 1 sweep.
PatternMatrix Traversal

Instinct A 2D grid you must walk in a fixed geometric order (spiral, diagonal, layer, rotate) or update in place - think boundaries, direction vectors and index maths.

Memory hack Walk the walls, then shrink the room - four fences (top, bottom, left, right) close in after every lap.

Open the Matrix Traversal guide →

Approaches

Brute ForceFull Snapshot Copy

Time O(m·n)Space O(m·n)

Copy the whole grid first. Every neighbour count reads the frozen copy, so cells that were already rewritten in board can’t corrupt later counts — that is exactly the “simultaneous update” rule.

Java
public void gameOfLife(int[][] board) {
    int m = board.length, n = board[0].length;
    int[][] old = new int[m][];
    for (int r = 0; r < m; r++) old[r] = board[r].clone();
    for (int r = 0; r < m; r++) {
        for (int c = 0; c < n; c++) {
            int live = 0;
            for (int dr = -1; dr <= 1; dr++) {
                for (int dc = -1; dc <= 1; dc++) {
                    if (dr == 0 && dc == 0) continue;
                    int nr = r + dr, nc = c + dc;
                    if (nr >= 0 && nr < m && nc >= 0 && nc < n) live += old[nr][nc];
                }
            }
            if (old[r][c] == 1) board[r][c] = (live == 2 || live == 3) ? 1 : 0;
            else board[r][c] = (live == 3) ? 1 : 0;
        }
    }
}

Obviously correct, but doubles the memory.

At a glance

LevelApproachTimeSpace
Brute ForceFull Snapshot CopyO(m·n)O(m·n)
BetterRolling Two-Row BufferO(m·n)O(n)
OptimalTwo-Bit In-place EncodingO(m·n)O(1)
Common pitfalls
  • Updating cells in-place with plain 0/1 — later neighbours read already-updated values.
  • Counting the centre cell as its own neighbour.
  • Reading board[x][y] instead of board[x][y] & 1 once bit 1 can be set.
Interview tips
  • Start with the copy, then ask “what do I really need to remember?”
  • Condense the rules: next = (live == 3) || (alive && live == 2).
  • Mention the infinite-board follow-up: sparse set of live cells.
Pattern
In-place state encoding → simultaneous grid updates where old and new values must coexist in the same cell.
My notes saved in this browser