Skip to content

Coding patternsBlind 75

Unique Paths

The routes into a cell are the routes into the cell above plus the routes into the cell to its left, so fill the grid row by row, keeping just one row. O(m × n) time and O(n) space, with a step-through, code in five languages and the Big O worked out from the code.

A robot stands in the top left cell of a grid with rows rows and columns columns (call them m and n). Each move takes it one cell right or one cell down. Return how many different routes take it to the bottom right cell.

Example 1

Input: rows = 3, columns = 4

Output: 10

Every route makes 3 moves right and 2 moves down, in some order. There are 10 such orders.

0123
0start
1
2end

Example 2

Input: rows = 1, columns = 5

Output: 1

A single row: the only route is straight right.

Example 3

Input: rows = 3, columns = 3

Output: 6

2 rights and 2 downs, in 6 orders.

  • 1 ≤ m, n ≤ 100
  • The answer is at most 2 × 10⁹.
Can the robot move up or left?
No. Only right and down, so it can never revisit a cell.
Are there blocked cells?
No. (Unique Paths II adds obstacles.)
What if the grid is a single cell?
Then the robot is already there: 1 route, making no moves.

Look at the last move into a cell. It came from the cell above or the cell to the left, never both. So the routes into a cell are the routes into those two cells added together. Each answer is built from smaller answers that are shared by many cells: dynamic programming on a grid.

There is no brute force tab. Following every route one by one takes as many steps as there are routes, up to 2 billion. A counting formula, choosing which moves go down, also works, but needs care with overflow.

One row O(m × n)

A cell only reads the cell above it and the cell to its left. So the table never needs more than one row.

Keep a single array paths, all 1s, for the top row. For each next grid row, walk left to right and do paths[column] += paths[column - 1]. Before the write, paths[column] still holds the value from the row above. And paths[column - 1] was just updated, so it is the cell to the left in the current row. paths[0] stays 1, like the left column.

Why it is correct: it performs the same additions as the full table, in the same order. The values it overwrites are never needed again.

paths
10111213
grid row
0
  1. paths = [1] * columns
  2. for row in 1 .. rows - 1:
  3. for column in 1 .. columns - 1:
  4. paths[column] += paths[column - 1]
  5. return paths[columns - 1]

Each cell needs only the cell above and the cell to its left. So one row is enough: before a cell is updated, it still holds the value from the row above.

1 / 8
Solution.javasolution.pySolution.cssolution.gosolution.ts
class Solution {
// One row: each row only needs the row above it, so update a single row in
// place, left to right. O(m × n) time, O(n) space.
public int uniquePaths(int rows, int columns) {
int[] paths = new int[columns];
java.util.Arrays.fill(paths, 1);
for (int row = 1; row < rows; row++) {
for (int column = 1; column < columns; column++) {
// Before the write, paths[column] still holds the cell above;
// paths[column - 1] is already the cell to the left.
paths[column] += paths[column - 1];
}
}
return paths[columns - 1];
}
}
Time O(m × n)Space O(n)Here is how we get these from the code, in four steps.
  1. 1 Find the work that repeats

    Setting up the row writes n numbers. The inner loop does one addition per run. Each is a fixed job, so 1 step.

    1. paths = [1] * columns
    2. for row in 1 .. rows - 1:
    3. for column in 1 .. columns - 1:
    4. paths[column] += paths[column - 1]
    5. return paths[columns - 1]
  2. 2 Count the runs on Example 1

    Rows 1 and 2 each update 3 cells.

    4 set + 3 + 3 = 10 steps.

    row12
    inner runs33
    total
    4 set + 6 sums = 10
  3. 3 Write the count for any n

    n + (m − 1) × (n − 1) steps

    Check it with Example 1: 4 + 2 × 3 = 10. That matches the count.

  4. 4 Keep only the part that grows fastest

    Drop the lone n and the − 1s. What is left is m × n. The time is the same as the grid table.

    So the time is O(m × n).

  5. S Space: count the extra memory the same way

    One row of n numbers. So the space is O(n). Swapping m and n, if n is the bigger one, brings it down to O(min(m, n)).

    paths (n)

2,000 random grids from 1 x 1 to 12 x 12, with many thin grids of one row or one column. The grid table and the one row gave the same answer every time, and matched a counting formula written in the test.

Largest inputsResult
100 x 7 and 7 x 100, the largest grids whose answer fits the 2 × 10⁹ limit. One row.Under 0.001 s, and under 0.01 MB of extra memory: one row of counts.
100 x 7. Grid table.Under 0.001 s, and about 0.02 MB: the full table of 700 counts. The one row gives the same answer with a fraction of the memory.