11

Matrices & Simulation

A grid is an array with two indices. Master the index maths, then rotate, spiral and simulate it in place.

intermediate~60 min5 simulations5 problems

▶ guided lesson⚡ 1-minute summary↻ 14 recall cards

before this: Arrays & Strings · Java Arrays & Strings

01 · why it exists

Why this exists, and the weight it carries

since1957 · 1972

Row-major layout & index maths

John Backus's IBM FORTRAN team (column order); Dennis Ritchie at Bell Labs (C, row order)

A grid has rows and columns, but memory is one long line of numbered slots. Every language must decide which cell comes next. FORTRAN (IBM, 1957) chose columns: the 1957 paper's address formula for A(I, J, K) multiplies J by the size of the first dimension, so the first subscript moves fastest. C, which grew up at Bell Labs between 1969 and 1973, chose rows: the C standard says arrays are stored in row-major order, the last subscript varying fastest. Java (1996) made int[][] an array of references to row arrays (JLS chapter 10). Each row is its own int[], so walking along a row is the fast direction.

the problem it solvedTurning a two-dimensional table into addresses in one-dimensional memory, with one multiply and one add per lookup.

its jobs today

  • Images: Java's BufferedImage.getRGB returns pixels in one int[], pixel (x, y) at y × scansize + x (with zero offsets).
  • Grid problems turn a cell into one int id, r * cols + c, for visited arrays, union-find and hash sets.
  • Numeric libraries such as NumPy let you pick row-major ('C') or column-major ('F') order, because the two styles meet in real code.

the weight it carries

Illustrative: a 1920 × 1080 screenshot = 20,73,600 pixels. Pixel (x = 100, y = 500) sits at 500 × 1920 + 100 = 9,60,100: one multiply, one add. Assume 64-byte cache lines, so 16 ints per line: a row-by-row walk then misses about once per 16 pixels: 20,73,600 / 16 = 1,29,600 misses. A column-by-column walk over a big image can miss on almost every pixel.

without it

Every grid would need its own map from (row, col) to memory, and image buffers, flat visited arrays and cell ids like r * cols + c would all be ad hoc.

when · why · how

when
You need one number per cell (visited, union-find, a set key), a flat buffer, or you walk a large grid.
why
O(1) both ways: i = r·cols + c, r = i / cols, c = i % cols. Row-order loops follow memory order, which caches love.
how
int id = r * cols + c; back with id / cols and id % cols. Loop r outside and c inside. Switch to long past about 2.1 × 10⁹ cells.

02 · plain english

The idea in 30 seconds

A matrix looks like a grid, but memory is one long line. So every grid is stored row after row, and cell (r, c) is number r × cols + c on that line.

With that index maths and a small table of directions, you can walk a grid in any order: rows, rings, diagonals, zigzags, neighbours.

Most grid questions are careful simulations: change the cells in place without destroying information you still need.

picture this

Your laptop screen. 1920 × 1080 pixels look like a grid, but the image sits in RAM as one long run of numbers, line after line. Java's BufferedImage.getRGB hands pixels back in one int[], with pixel (x, y) at index y × scansize + x (with its offsets at 0): row y first, then column x. Rotate a photo, blur it, or count Minesweeper neighbours, and you are doing this chapter's index maths.

03 · remember

What you must know

  • Row-major: cell (r, c) is index r * cols + c of one long line. The way back is r = i / cols, c = i % cols. Always divide by cols, never by rows.
  • Java's `int[][]` is an array of row arrays. Each row is its own int[]. Loop r outside and c inside, so you read each row in memory order.
  • Direction arrays: keep moves in a table like {{-1,0},{0,1},{1,0},{0,-1}} (clockwise). Turning right is (d + 1) % 4. Check the bounds before you read a neighbour.
  • Layer by layer: four walls (top, bottom, left, right). Walk one side, push that wall inwards, and stop when the walls cross.
  • Rotation = two mirrors: a clockwise quarter turn sends (r, c) to (c, n − 1 − r). Transpose, then reverse every row. O(1) extra space.
  • Mark first, write later: when one cell's change affects a whole row or column, record what must happen, then do it. Row 0 and column 0 can be the notebook.
  • Two states in one cell: bit 0 = the value now, bit 1 = the value next. Read & 1, plan with |= 2, finish with >>= 1.
  • Simulation discipline: read only from the old state, write only to the new one. Mixing them is the classic Game of Life bug.
  • Rectangles, not squares: test 1 × 1, 1 × n, n × 1 and 3 × 4. Most grid bugs hide in a single leftover row or column.

04 · see it

Play with it in 3D

Press Space to play, ←/→ to step, drag to move, ? for all shortcuts. Try your own input.

sim

Row-major: one grid, one long line

Each row becomes one unbroken run of the flat array. (r, c) lands at r × cols + c, and i / cols, i % cols takes you back.

loading simulation…
sim

Spiral order with four shrinking walls

Walk a side, push that wall in. The two guards stop a single leftover row or column from being walked twice.

loading simulation…
sim

Rotate 90°: transpose, then reverse each row

The transpose turns rows into columns. Reversing each row finishes the clockwise turn.

loading simulation…
sim

Row 0 and column 0 as a notebook

Phase 1 writes the marks, phase 2 obeys them. Row 0 and column 0 are cleared last, so no mark is lost early.

loading simulation…
sim

Game of Life generations, in place

Bit 0 is now, bit 1 is next. No cell's 'now' bit changes until every cell has been decided.

loading simulation…

05 · cost

Time & space, explained

Grid operations (m rows × n columns)
TimeExtra spacewhy
Read or write grid[r][c]O(1)O(1)Two index steps: find row r's array, then slot c in it.
Flat index r * cols + c and backO(1)O(1)One multiply and one add; back is one divide and one remainder.
Visit every cell (rows, spiral, diagonals, zigzag)O(m·n)O(1)Each cell is visited once. Only the order changes.
Check all 8 neighbours of every cellO(m·n)O(1)8 constant-time checks per cell: 8·m·n steps.
Transpose m × n into a new n × mO(m·n)O(m·n)The shape changes, so a new matrix is unavoidable.
Transpose a square matrix in placeO(n²)O(1)n(n − 1)/2 swaps above the diagonal, one temp variable.
Deep-copy a gridO(m·n)O(m·n)Every row is cloned.
The same answers, less memory
TimeExtra spacewhy
Set Zeroes: copy, then wipe rows and columnsO(m·n·(m + n))O(m·n)Each original 0 wipes m + n cells; the copy is a full second matrix.
Set Zeroes: row and column flagsO(m·n)O(m + n)Two passes; one boolean per row and per column.
Set Zeroes: row 0 and column 0 as markersO(m·n)O(1)Same two passes; the marks live inside the matrix, plus two booleans.
Game of Life: copy the boardO(m·n)O(m·n)8 checks per cell, reading from a frozen copy.
Game of Life: two bits per cellO(m·n)O(1)The same checks; the next state hides in bit 1 until a final shift.
Rotate: copy vs transpose + reverseO(n²)O(n²) vs O(1)Both move every cell a constant number of times; only the copy needs a second matrix.
Spiral: visited grid vs four wallsO(m·n)O(m·n) vs O(1)Both visit each cell once; the walls replace the visited grid.
Zigzag: draw a grid / row builders / cycle jumpsO(rows·n) / O(n) / O(n)O(rows·n) / O(n) / O(1)The grid has rows × n cells to scan; builders hold n chars; jumps compute every position (besides the output).

06 · java

Raw vs Collections Framework

Row-major index maths

javaflatten and map backjava.util.*
class RowMajor {    /** Copies an m x n grid into one int[], row by row: cell (r, c) lands at index r * cols + c. */    static int[] flatten(int[][] grid) {        int rows = grid.length, cols = grid[0].length;        int[] flat = new int[rows * cols];        for (int r = 0; r < rows; r++) { // row r starts at index r * cols            for (int c = 0; c < cols; c++) {                flat[r * cols + c] = grid[r][c];            }        }        return flat;    }     /** The way back: index i is in row i / cols and column i % cols. Divide by cols, not rows. */    static int[] cellOf(int i, int cols) {        return new int[] {i / cols, i % cols};    }}
  • grid.length is the number of rows; grid[0].length is the number of columns (for a rectangle).
  • r * cols + c turns a cell into one int. That's handy as a visited index, a union-find id or a HashSet<Integer> key, instead of an int[] pair.
  • The way back divides by cols: index 6 in a 4-column grid is row 6 / 4 = 1, column 6 % 4 = 2.
  • For a big grid, r * cols + c can overflow int once rows × cols passes about 2.1 × 10⁹. Use long then.

Direction arrays

java4 and 8 neighboursjava.util.*
class Directions {    // Clockwise from "up": turning right is d + 1, turning back is d + 2 (both % 4).    static final int[][] DIRS4 = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};    static final int[][] DIRS8 = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};     /** How many of the 8 cells around (r, c) hold a 1. Cells outside the grid don't exist. */    static int liveNeighbours(int[][] grid, int r, int c) {        int count = 0;        for (int[] d : DIRS8) {            int nr = r + d[0], nc = c + d[1];            if (nr >= 0 && nr < grid.length && nc >= 0 && nc < grid[0].length) count += grid[nr][nc];        }        return count;    }     static int turnRight(int d) {        return (d + 1) % 4;    }}
  • Store moves as {dr, dc} pairs. One loop plus one bounds check replaces 4 or 8 copy-pasted if blocks.
  • Keep the 4 directions in clockwise order. Then turning right is (d + 1) % 4 and turning around is (d + 2) % 4.
  • Check nr >= 0 && nr < rows && nc >= 0 && nc < cols before grid[nr][nc]. The && stops early, so the read never runs out of bounds.

Diagonals by index

javar − c and r + cjava.util.*
class Diagonals {    /** Sum of the "\" diagonal through (r, c): every cell on it has the same r - c. */    static int diagonalSum(int[][] grid, int r, int c) {        int sum = 0;        for (int i = 0; i < grid.length; i++)            for (int j = 0; j < grid[0].length; j++)                if (i - j == r - c) sum += grid[i][j];        return sum;    }     /** Cells grouped by anti-diagonal ("/"): r + c runs from 0 to rows + cols - 2. */    static List<List<Integer>> antiDiagonals(int[][] grid) {        int rows = grid.length, cols = grid[0].length;        List<List<Integer>> out = new ArrayList<>();        for (int k = 0; k <= rows + cols - 2; k++) out.add(new ArrayList<>());        for (int r = 0; r < rows; r++)            for (int c = 0; c < cols; c++) out.get(r + c).add(grid[r][c]);        return out;    }}
  • Along a ↘ diagonal, r - c stays the same. Along a ↙ anti-diagonal, r + c stays the same.
  • r + c runs from 0 to rows + cols − 2. r - c can be negative, so add cols - 1 before using it as an array index.
  • N-Queens uses exactly this: one boolean per r + c and one per r - c tells you if a diagonal is already attacked.

Transpose: a new matrix or in place

javam × n → n × m, and square in placejava.util.*
class Transpose {    /** m x n becomes n x m. The shape changes, so it needs a new matrix. */    static int[][] transpose(int[][] m) {        int rows = m.length, cols = m[0].length;        int[][] t = new int[cols][rows];        for (int r = 0; r < rows; r++)            for (int c = 0; c < cols; c++) t[c][r] = m[r][c];        return t;    }     /** Square only: swap across the main diagonal, each pair once (c starts at r + 1). */    static void transposeInPlace(int[][] m) {        for (int r = 0; r < m.length; r++)            for (int c = r + 1; c < m.length; c++) {                int tmp = m[r][c];                m[r][c] = m[c][r];                m[c][r] = tmp;            }    }}
  • A rectangle changes shape when transposed (3 × 4 → 4 × 3), so it needs a new matrix.
  • A square can be transposed in place. Start c at r + 1: starting at 0 swaps every pair twice and changes nothing.
  • Transpose + reverse each row = rotate clockwise. Transpose + reverse each column = rotate counter-clockwise.

Copying a grid

javaclone every rowjava.util.*
class CopyGrid {    /** A real copy: clone every row. grid.clone() alone copies only the outer array of row references. */    static int[][] deepCopy(int[][] grid) {        int[][] copy = new int[grid.length][];        for (int r = 0; r < grid.length; r++) copy[r] = grid[r].clone();        return copy;    }}
  • grid.clone() is shallow: the JLS (§10.7) says the subarrays are shared. Changing copy[0][0] would change grid[0][0] too.
  • Clone each row: copy[r] = grid[r].clone(). The stream version does the same with map(int[]::clone).
  • Print a grid with Arrays.deepToString(grid) and compare two grids with Arrays.deepEquals(a, b).

Two states in one cell

javabit 0 = now, bit 1 = nextjava.util.*
class TwoStates {    // One int, two facts: bit 0 = the value now, bit 1 = the value in the next round.    static int now(int cell) {        return cell & 1;    }     static int withNext(int cell, int next) {        return cell | (next << 1);    }     static int advance(int cell) {        return cell >> 1; // the next value becomes the current one    }}
  • When cells hold only 0 or 1, the higher bits are free. Bit 1 can carry the next state without touching bit 0.
  • Neighbours read cell & 1, so they still see the old generation while you plan the new one.
  • cell >> 1 moves the plan into place. The same idea works with any small encoding, like 2 = 'was dead, now alive'.
Java API you will actually use
calldoescost
new int[rows][cols]A rows × cols grid of 0s (one int[] per row)O(rows·cols)
grid.length / grid[0].lengthNumber of rows / columnsO(1)
grid[r].clone()Copy one rowO(cols)
Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new)Deep copy in one lineO(rows·cols)
Arrays.fill(grid[r], 0)Set a whole row to one valueO(cols)
Arrays.deepToString(grid) / Arrays.deepEquals(a, b)Print / compare 2D contentsO(rows·cols)
x & 1 / x | 2 / x >> 1Read bit 0 / set bit 1 / shift bit 1 into bit 0O(1)
new StringBuilder[k]k slots that start as null: create each builder before useO(k)

One number per cell (visited, union-find, set key)

→ r * cols + c

A single int instead of an int[] pair or a String key; O(1) both ways.

Look at neighbours, or walk and turn

→ A DIRS array + one bounds check

One loop for 4 or 8 directions; turning is (d + 1) % 4.

Spiral or ring order

→ Four walls: top, bottom, left, right

O(1) extra space instead of a visited grid.

Rotate or flip a square in place

→ Transpose + reverse

Two easy loops, one temp variable.

New state depends on old neighbours

→ A copy (simple) or bits in the cell (O(1) space)

Readers must keep seeing the old generation.

Mark rows or columns for later

→ boolean[] rows, cols, or row 0 / column 0 of the matrix

O(m + n) and clear, or O(1) with careful ordering.

07 · recognise

Spot the pattern

"Spiral order", "layer by layer", "ring"

Four shrinking walls, with guards for a single leftover row or column

"Rotate the image 90°" in place, n × n

Transpose, then reverse every row

"If a cell is 0, set its whole row and column to 0"

Mark first, write later; row 0 and column 0 as markers

"All cells update at the same time", "next generation", "next state"

Read old, write new: a copy, or two bits per cell

"Write it in a zigzag", "rails", "up and down the rows"

One builder per row with a direction that flips, or a cycle of 2·rows − 2

"Neighbours", "adjacent", "8 directions"

A DIRS array with one bounds check

"The k-th cell", "treat the matrix as one sorted list"

Flat index: i = r·cols + c, back with i / cols and i % cols

"Diagonal", "anti-diagonal"

r − c is fixed on ↘, r + c is fixed on ↙

08 · traps & tricks

Mistakes to avoid, tricks to use

traps

  • Un-flattening with i / rows instead of i / cols. It only works by luck on square grids.
  • grid.clone() copies only the outer array. The rows are shared, so your "copy" changes the original.
  • Updating a cell while other cells still need its old value (Game of Life, Set Matrix Zeroes). Freeze a copy or encode old + new.
  • Zeroing row 0 or column 0 before the inner cells have used them as markers. Markers go last.
  • Transposing with c starting at 0: every pair is swapped twice, and nothing changes.
  • Spiral without the top <= bottom / left <= right guards: a single leftover row is walked forwards and then backwards.
  • Marking cells with a "special" value like −1 or Integer.MIN_VALUE when every int is a legal cell value.
  • new StringBuilder[k] gives k nulls, not k builders. Calling append on one throws NullPointerException.
  • Mixing up (x, y) and (r, c). x is the column and y is the row, so pixel (x, y) is grid[y][x].

tricks

  • Before any transform, write the mapping: (r, c) → (?, ?). Rotation, transpose and flips all follow from it.
  • Draw a 3 × 4 rectangle, not a square. Then test 1 × 1, 1 × n and n × 1 before you say "done".
  • For simulations, say out loud: "I read from the old state and write to the new one." Interviewers listen for that sentence.
  • Name your bounds once: int rows = grid.length, cols = grid[0].length;. Fewer chances to mix them up later.
  • Chalo, dry-run karte hain: take a 3 × 3 on paper, write the variables as columns, and fill one line per step. Grid bugs show up by the third line.

09 · why & how

Questions you might be too shy to ask

Is Java's int[][] stored row by row, like in C?

Almost. In C, a 2D array is one block, row after row. In Java, int[][] is an array of references to row arrays (JLS chapter 10). Each row is its own int[], but the rows can sit anywhere in the heap. Reading along a row is still the fast direction. Need one truly continuous block? Use a flat int[rows * cols] with r * cols + c.

Why does i / cols give the row?

Every row holds exactly cols cells. So the first cols indices are row 0, the next cols are row 1, and so on. Dividing by cols counts how many full rows come before index i. The remainder i % cols is how far into that row you are.

Why is "up" written as {-1, 0}? In maths, up is +1.

In a grid, row 0 is at the top and row numbers grow as you go down, like lines in a file or pixels on a screen. So moving up means going to a smaller row: r - 1. Moving down is r + 1, left is c - 1, right is c + 1. That's why {{-1,0},{0,1},{1,0},{0,-1}} reads up, right, down, left: clockwise.

Rotate Image: how do I work out (r, c) → (c, n − 1 − r) myself instead of memorising it?

Watch one row. After a clockwise turn, the top row becomes the right column, and row 1 becomes the column just left of it. So old row r lands in column n − 1 − r. Along that row, left-to-right becomes top-to-bottom, so old column c becomes row c. Check on the 3 × 3 example: 7 sits at (2, 0) and moves to (0, 0) — the top-left of [[7,4,1],…].

How do I rotate counter-clockwise, or by 180°?

Counter-clockwise: transpose, then reverse each column (or reverse each row first, then transpose). 180°: reverse the order of the rows, then reverse each row. Or rotate clockwise twice. Write the mapping first: 180° sends (r, c) to (n − 1 − r, n − 1 − c).

Spiral Matrix: why is the loop top <= bottom, with <=, and not top < bottom?

When top == bottom, one row is still left to print. Take [[1, 2, 3]]: top = 0 and bottom = 0 at the start. With <, the loop never runs and you return an empty list. The walls are inclusive — both top and bottom are rows you still have to print. Same for left and right.

Spiral Matrix: why don't the corner cells get printed twice?

Each corner belongs to exactly one side, because a wall moves right after its side is walked. The top row prints both top corners, then top++. So the right column starts one row lower and skips the top-right corner. Then right--, so the bottom row skips the bottom-right corner. Then bottom--, so the left column skips the bottom-left one. Dry-run a 3 × 3 once with the sim and watch the four walls move. Simple hai.

Zigzag Conversion: why is one cycle 2 * numRows - 2 characters and not 2 * numRows?

The top and bottom rows are visited only once per trip; the middle rows are visited twice. With numRows = 4, going down covers rows 0, 1, 2, 3 (4 characters). Coming back up covers only rows 2 and 1 (2 characters), because row 3 and row 0 belong to the next trip. That's 4 + 2 = 6 = 2 · 4 − 2. Row 0 then takes indices 0, 6, 12, …

Does the output list count as extra space in Spiral Matrix or Zigzag?

No. By the usual interview convention, the space you must return doesn't count. Say it out loud: "O(1) extra space besides the output."

Set Matrix Zeroes: why can't I zero a row as soon as I find a 0?

Because the zeros you write look exactly like original zeros. When the scan reaches them, it wipes more rows and columns that should have stayed. Record which rows and columns must go first, then write.

Why is it safe to write the markers into row 0 and column 0?

A mark in matrix[r][0] means row r will become all zeros, so that cell was going to be 0 anyway. The same holds for matrix[0][c]. The only facts you'd lose are row 0's and column 0's own zeros, so you save those in two booleans before marking.

Game of Life: why not update each cell in one pass?

Every cell must change at the same moment. If you update (0, 0) first, then (0, 1) counts the new (0, 0) instead of the old one, and the generation comes out wrong. Keep the old state readable: a copy, or the old state in bit 0.

Game of Life: I've never used & 1, |= 2 and >>= 1. What are they actually doing?

Think of each cell as a two-digit binary number: the right digit is now, the left digit is next. So 0 = 00, 1 = 01, 2 = 10, 3 = 11. cell & 1 reads only the right digit (now). That's why a cell holding 2 (born next) still counts as dead for its neighbours: 2 & 1 = 0. cell |= 2 sets the left digit to 1 ("alive next") without touching the right one. cell >>= 1 drops the right digit, so next becomes now: 3 → 1, 2 → 1, 1 → 0, 0 → 0.

In the interview, can I just use a copy instead of the in-place trick?

Read the problem first. Rotate Image says "do not allocate another matrix", so a copy breaks the rule there. Set Matrix Zeroes asks for in place, and its follow-up asks for O(1) space: the row and column flags (O(m + n)) are a good first answer. In Game of Life, solving it in place is the follow-up, so a copy first is fine. Say the cost out loud. Then offer the in-place version: "I can drop the extra space by keeping the marks inside the matrix." A working simple answer beats a half-written clever one.

10 · practice

Interview problems

Every problem has brute → better → optimal solutions in Java, with complexity and a dry run.

  1. #48
    Rotate Imagemust-do
    MediumMicrosoftAppleBloombergAmazonGoogle+1
  2. #54
    Spiral Matrixmust-do
    MediumByteDance / TikTokOracleAppleMicrosoftAmazon+1
  3. #6
    Zigzag Conversion
    MediumPayPalWalmartAmazonGoogleMicrosoft
  4. #73
    Set Matrix Zeroesmust-do
    MediumWalmartBloombergMicrosoftMetaAmazon+1
  5. #289
    Game of Lifemust-do
    MediumMicrosoftAmazonGoogle

Also practise this here

Each problem has one home page in the course; these use this chapter's idea too. The note says what to look for.

  1. #1672
    Richest Customer Wealth
    Easyin Java Arrays & Strings

    A warm-up: walk each row of an int[][] and keep the best row sum.

  2. #74
    Search a 2D Matrix
    Mediumin Binary Search

    Read row by row, the matrix is one sorted list: binary search over i = 0 … m·n − 1 and turn i into (i / cols, i % cols).

  3. #36
    Valid Sudoku
    Mediumin Hashing

    Index maths on boxes: cell (r, c) is in box (r / 3) * 3 + c / 3.

  4. #304
    Range Sum Query 2D - Immutable
    Mediumin Hashing

    Precompute a 2D prefix-sum grid so any rectangle sum is O(1).

  5. #200
    Number of Islands
    Mediumin Graphs

    The DIRS array from this chapter, used to flood-fill a grid.

  6. #51
    N-Queens
    Hardin Backtracking

    r + c and r − c identify the two diagonals a queen attacks.

11 · revise

The whole chapter on one screen

9 cards, about a minute. Read them the night before an interview, or right after the chapter to lock it in.

  1. what it is

    A matrix is rows of equal arrays. Row-major: (r, c) is cell r * cols + c of one long line; back with i / cols and i % cols.

  2. use it when

    Spiral → four walls. Rotate → transpose + reverse. Row/column wipes → markers. "All cells at once" → old vs new. Zigzag → row builders.

  3. template

    Neighbours: for (int[] d : DIRS) { int nr = r + d[0], nc = c + d[1]; if (nr >= 0 && nr < m && nc >= 0 && nc < n) … }

  4. template

    Two states in a cell: read cell & 1, plan cell |= 2, then cell >>= 1. Markers: matrix[r][0] = 0; matrix[0][c] = 0;

  5. cost

    Every walk here is O(m·n) time. Only the space differs: a copy O(m·n) → flags O(m + n) → markers or spare bits O(1).

  6. trap

    Writing cells while you still read their old values breaks Game of Life and Set Zeroes. Freeze a copy, or keep old + new in one cell.

  7. trap

    grid.clone() shares rows. i / rows instead of i / cols. Transposing with c from 0 swaps each pair twice.

  8. trap

    Spiral: without the top <= bottom and left <= right guards, a single leftover row or column is walked twice.

  9. pro tip

    Draw a 3 × 4 rectangle, not a square. Then test 1 × 1, 1 × n and n × 1 before you say done.

12 · recall

Flip, remember, repeat

card 1 / 14
recall

Cell (r, c) of an m × n grid, row-major: its flat index? And the way back?

tap or Space to flip ↻

Question 1: Cell (r, c) of an m × n grid, row-major: its flat index? And the way back?

13 · check yourself

Quick quiz

  1. In a 3 × 5 grid stored row-major, which cell is at index 11?

  2. `int[][] b = a.clone(); b[0][0] = 9;` What happens to `a[0][0]`?

  3. Rotating an n × n matrix 90° clockwise in place can be done by…

  4. Spiral order on [[1, 2, 3]] with the four-wall loop but WITHOUT the two inner guards returns…

  5. Set Matrix Zeroes with row 0 and column 0 as markers needs how much extra memory?

  6. Game of Life with two bits per cell: after pass 1 a cell holds 2. What does that mean?

  7. Zigzag Conversion with numRows = 4: which indices of s land in row 0?