2Brute2Best
🔥0

Unique Paths

Medium·LeetCode #62Basic Anchor
LeetCode
30-Second Mental ModelDP — Grid, Paths in a grid (count: dp[r][c] = dp[r−1][c] + dp[r][c−1])
Complexity:O(2^(M + N))→O(M · N)
Key Insight

Only one row of counts is needed. Row r is built from row r − 1 and the cell to its left. Going left to right, row[c] += row[c − 1] turns the old row into the new one. Before that line runs, row[c] still holds the cell above, and row[c − 1] already holds the cell to the left.

Core Validity Invariant

After row r is done, row[c] is the number of paths to cell (r, c), because the update adds exactly the cell above and the cell to the left.

01

Problem

A robot stands in the top-left corner of a grid with m rows and n columns. It wants to reach the bottom-right corner. Each move takes it one cell down or one cell right. It never moves up or left.

Return how many different paths it can take.

Input

Two whole numbers: m, the number of rows, and n, the number of columns.

Output

The number of different paths from the top-left cell to the bottom-right cell.

Example 1
Input: m = 3, n = 7
Output: 28

A path has 2 downs and 6 rights, in some order. Choose which 2 of the 8 moves are down: C(8, 2) = 28.

Example 2
Input: m = 3, n = 2
Output: 3

The three paths are Right → Down → Down, Down → Down → Right and Down → Right → Down.

Constraints
  • • 1 ≤ m, n ≤ 100
  • • The tests are chosen so that the answer is at most 2 × 10^9.
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    Every path has the same number of moves. How many moves is that, in terms of m and n?

  2. 2.

    The robot never moves up or left. What does that say about how many downs and rights every path has?

  3. 3.

    To reach a cell that is not in the top row or the left column, what was the last move?

  4. 4.

    If I know how many paths reach the cell above and the cell to its left, how do I count the paths to this cell?

  5. 5.

    Would the length of the shortest route to the corner tell me how many routes there are? Why or why not?

03

Brute force approach

04

Better approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceCount the paths into a cell by adding the counts of the two cells that can feed itO(2^(M + N))O(M + N)
Betterdp[r][c] = dp[r−1][c] + dp[r][c−1], with every cell worked out once and storedO(M · N)O(M · N)
OptimalKeep one row of counts; for each cell, row[c] += row[c − 1]O(M · N)O(N)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “move only down or right”A cell can only be entered from above or from the left. The last move decides which counts to add.
  • “how many different paths”The goal is a count, not a shortest distance. Add the counts of the cells that feed each cell.
  • “from the top-left to the bottom-right”The answer for the corner is built from the answers for the cells before it, so fill the table in order.
cell (r, c)+two feeders: (r−1, c) and (r, c−1)+count the ways into the cell+dp = above + left→DP — Grid, Paths in a grid (count: dp[r][c] = dp[r−1][c] + dp[r][c−1])

This is the anchor of the Paths sub-pattern. Every cell's count is the sum of the two cells that can feed it, and the top row and the left column start at 1. No cell is blocked here, so there is no validity rule at all. The next questions change one rule each: an obstacle forces a count to 0, a cost turns the sum into a minimum, and more feeding cells change the list of neighbours.

10

Don't make this mistake

Pattern confusion: shortest-path search (BFS)
✗ return dist[m - 1][n - 1]; // BFS: the number of moves to the corner
✓ return dp[m - 1][n - 1]; // the number of paths to the corner

Every path to the bottom-right corner has the same length, m + n − 2 moves, so a BFS only finds that length. On a 3 × 3 board the BFS reaches the corner after 4 moves, but there are 6 paths. A length does not tell you how many routes there are.

Pattern confusion: listing every path without a table

Walking every path (DFS or plain recursion) counts the paths one by one. On a 10 × 10 board the plain recursion makes 97,239 calls for 100 cells. The number of paths grows much faster than the number of cells, so the table, which does M · N steps, is the only version that scales.

Setting the first row or column to 0
✗ dp[0][c] = 0; // and dp[r][0] = 0
✓ dp[0][c] = 1; // and dp[r][0] = 1

A 0 on the edge stops the sums: every cell is built from edge cells, so every cell becomes 0. For 3 × 7 the table is all 0s, and the answer is 0 instead of 28.

Off-by-one: reading row m or column n
✗ return dp[m][n];
✓ return dp[m - 1][n - 1];

Rows are numbered 0 to m − 1 and columns 0 to n − 1, so index m (or n) is one past the end of the table. The answer is the bottom-right cell.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like DP — Grid translate into production architectures and low-level memory mechanics.