๐ Unique Paths - The Discovery Journey
How the human brain naturally discovers the DP solution
๐ Unique Paths Series:
- ๐ The Discovery Journey (You are here) - How humans naturally discover the solution
- Plain English Proof - Accessible logical reasoning
- Formal Proof - Mathematical rigor and certainty
- When Reality Gets Messy - Adapting to obstacles
A robot is located at the top-left corner of an m ร n
grid. The robot can only move either down or right at any point in time.
Goal: How many possible unique paths are there to reach the bottom-right corner?
Example: 3ร3 grid โ 6 unique paths
Constraints: All cells are reachable (no obstacles)
๐ง The Designer's Brain: The Messy Discovery Processโ
First Thought: "What if I just try all paths?"โ
You're at the top-left corner of a 3ร3 grid. You can only move right or down. Let's trace this out:
START (0,0)
โโ Go RIGHT to (0,1)
โ โโ Go RIGHT to (0,2)
โ โ โโ Go DOWN to (1,2)
โ โ โโ Go DOWN to (2,2) โ END
โ โ
โ โโ Go DOWN to (1,1)
โ โโ Go RIGHT to (1,2)
โ โ โโ Go DOWN to (2,2) โ END
โ โโ Go DOWN to (2,1)
โ โโ Go RIGHT to (2,2) โ END
โ
โโ Go DOWN to (1,0)
โโ Go RIGHT to (1,1)
โ โโ Go RIGHT to (1,2)
โ โ โโ Go DOWN to (2,2) โ END
โ โโ Go DOWN to (2,1)
โ โโ Go RIGHT to (2,2) โ END
โ
โโ Go DOWN to (2,0)
โโ Go RIGHT to (2,1)
โโ Go RIGHT to (2,2) โ END
Every path is a sequence of decisions. For a 3ร3 grid, you need:
- 2 moves RIGHT (R)
- 2 moves DOWN (D)
- Total: 4 moves
Wait... this is just asking: "In how many ways can I arrange 2 R's and 2 D's?"
RRDD
RDRD
RDDR
DRRD
DRDR
DDRR
That's 6 ways. Combinatorics: C(4,2) = 6.
๐ค But Wait... Let's Not Jump to Combinatorics Yetโ
The Recursive Insight (Usually the First Instinct)โ
Standing at any cell, I ask: "How many ways to reach the END from HERE?"
If I'm at cell (i,j)
:
- I can come from the cell ABOVE me
(i-1, j)
- I can come from the cell to my LEFT
(i, j-1)
paths_to(i,j) = paths_to(i-1,j) + paths_to(i,j-1)
Why addition? Because these are mutually exclusive events:
- Paths coming from above are DIFFERENT from paths coming from left
- No path can simultaneously come from both directions
๐ Let's Trace This on a 3ร3 Gridโ
I'll mark each cell with "how many ways to reach it from START (0,0)":
START
โ
1 โ 1 โ 1
โ โ โ
1 โ 2 โ 3
โ โ โ
1 โ 3 โ 6
โ
END
Why These Numbers?โ
Top row: Only ONE way (keep going right)
1 โ 1 โ 1
Left column: Only ONE way (keep going down)
1
โ
1
โ
1
Cell (1,1): Can come from:
(0,1)
which has 1 way(1,0)
which has 1 way- Total: 1 + 1 = 2 ways
Cell (1,2): Can come from:
(0,2)
which has 1 way(1,1)
which has 2 ways- Total: 1 + 2 = 3 ways
Cell (2,1): Can come from:
(1,1)
which has 2 ways(2,0)
which has 1 way- Total: 2 + 1 = 3 ways
Cell (2,2) - THE END: Can come from:
(1,2)
which has 3 ways(2,1)
which has 3 ways- Total: 3 + 3 = 6 ways โ
๐ก The Critical Insight (Prerequisite You Might Be Missing)โ
Why Does paths_to(i,j) = paths_to(i-1,j) + paths_to(i,j-1)
Work?โ
Property 1: Every path must make a FINAL MOVE
- You can't teleport to
(i,j)
- Your last step was either DOWN (from
i-1,j
) or RIGHT (fromi,j-1
)
Property 2: Partition Principle
ALL paths to (i,j)
can be split into two groups:
- Group A: Those whose final move was DOWN
- Group B: Those whose final move was RIGHT
These groups:
- Don't overlap (can't simultaneously do both as final move)
- Cover ALL possibilities (must come from somewhere)
Property 3: Bijection (One-to-One Mapping)
- Every path ending at
(i-1,j)
can be extended by one DOWN move to reach(i,j)
- Every path ending at
(i,j-1)
can be extended by one RIGHT move to reach(i,j)
- This creates a perfect correspondence
Therefore:
Total paths to (i,j) = |Group A| + |Group B|
= paths_to(i-1,j) + paths_to(i,j-1)
๐ป The Coder's Brain: Why This Data Structure?โ
Now that we understand the logic, how do we store this?
Option 1: Recursion (Mirrors Our Thought Process)โ
function paths(i, j):
if i == 0 or j == 0:
return 1 // base case: edges
return paths(i-1, j) + paths(i, j-1)
We recalculate the same cells many times!
paths(2,2) calls paths(1,2) and paths(2,1)
paths(1,2) calls paths(0,2) and paths(1,1)
paths(2,1) calls paths(1,1) and paths(2,0)
โ
calculated TWICE!
This creates an exponential time complexity! ๐ฑ
Option 2: 2D Array (Memoization of Recursion)โ
We already calculated this grid:
1 1 1
1 2 3
1 3 6
Because our state has TWO dimensions (row, column).
Each unique (i,j)
pair needs one storage slot.
The filling order matters:
- We need
(i-1,j)
and(i,j-1)
BEFORE we can fill(i,j)
- So fill left-to-right, top-to-bottom (like reading a book)
int[][] dp = new int[m][n];
// Base case: first row and column
for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int j = 0; j < n; j++) dp[0][j] = 1;
// Fill the grid
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
Option 3: 1D Array (Space Optimization)โ
To fill row i
, we only need row i-1
.
Previous row: [1, 2, 3]
Current row: [1, ?, ?]
To fill current[1]
:
- Need
previous[1] = 2
(from above) - Need
current[0] = 1
(from left) - Result: 1 + 2 = 3
Even better: We can overwrite the array in-place!
Start: [1, 1, 1] // represents row 0
After updating position 1:
[1, 2, 1] // position 1 now represents row 1
After updating position 2:
[1, 2, 3] // completed row 1
Full Implementation:
public int uniquePaths(int m, int n) {
int[] dp = new int[n];
Arrays.fill(dp, 1); // first row: all 1s
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[j] = dp[j] + dp[j-1];
// โ โ
// from above from left
}
}
return dp[n-1];
}
- 2D Array: O(m ร n)
- 1D Array: O(n)
- Same time complexity: O(m ร n)
๐จ Edge Cases as Concept Validatorsโ
Edge 1: 1ร1 Gridโ
START = END
- Already at destination
- Answer: 1 way (do nothing)
- Tests: Base case handling
Edge 2: 1รn Grid (Single Row)โ
START โ โ โ โ END
- Only one path (keep going right)
- Answer: 1
- Tests: Do we handle the "only right moves" case?
Edge 3: mร1 Grid (Single Column)โ
START
โ
โ
โ
END
- Only one path (keep going down)
- Answer: 1
- Tests: Do we handle the "only down moves" case?
Edge 4: Why Can't We Have 0 Paths?โ
As long as m โฅ 1
and n โฅ 1
, there's ALWAYS at least one path.
The grid's connectivity guarantees this.
Validates: Our understanding of the problem constraints.
๐ฏ The Meta-Process (Framework for ALL Problems)โ
Step 1: Start with the simplest possible approach
"What if I just try everything?" โ Recursion
Step 2: Find the pattern in the recursion
- Draw it out for small cases
- Look for repeated work
Step 3: Identify the state
- What information do I need to know? โ
(row, column)
- How many dimensions? โ 2D problem โ 2D array
Step 4: Find dependencies
- What do I need to calculate X? โ Dependency graph
- This determines filling order
Step 5: Optimize storage
- Do I need ALL previous states? โ Only previous row
- Can I reuse memory? โ 1D array
๐ Visual Summary: The Three Approachesโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ RECURSION (Intuitive but Slow) โ
โ โ
โ paths(2,2) โ
โ โโ paths(1,2) โ
โ โ โโ paths(0,2) = 1 โ
โ โ โโ paths(1,1) โ REPEATED! โ
โ โ โโ paths(0,1) = 1 โ
โ โ โโ paths(1,0) = 1 โ
โ โโ paths(2,1) โ
โ โโ paths(1,1) โ REPEATED! โ
โ โโ paths(2,0) = 1 โ
โ โ
โ Time: O(2^(m+n)) - EXPONENTIAL! ๐ฑ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 2D DP (Clear and Standard) โ
โ โ
โ 0 1 2 โ
โ โโโโโฌโโโโฌโโโโ โ
โ 0 โ 1 โ 1 โ 1 โ โ
โ โโโโโผโโโโผโโโโค โ
โ 1 โ 1 โ 2 โ 3 โ โ
โ โโโโโผโโโโผโโโโค โ
โ 2 โ 1 โ 3 โ 6 โ โ Answer โ
โ โโโโโดโโโโดโโโโ โ
โ โ
โ Time: O(mรn) Space: O(mรn) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 1D DP (Space Optimized) โ
โ โ
โ Initial: [1, 1, 1] โ
โ After i=1: [1, 2, 3] โ
โ After i=2: [1, 3, 6] โ Answer at dp[2] โ
โ โ
โ Time: O(mรn) Space: O(n) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐งช Test Your Understandingโ
Question 1: In a 4ร4 grid, how many ways to reach cell (2,2)
?
Hint: Build the grid up to that point:
1 1 1 1
1 2 3 4
1 3 ? ?
Click for answer
Cell (2,2) = dp[1][2] + dp[2][1]
= 3 + 3
= 6 ways
Full grid:
1 1 1 1
1 2 3 4
1 3 6 10
Question 2: Why can't we fill the grid in reverse (bottom-right to top-left)?
Hint: Think about dependencies.
Click for answer
Each cell (i,j)
depends on (i-1,j)
and (i,j-1)
(cells above and to the left).
If we start from bottom-right, we'd need values that haven't been calculated yet!
Exception: We COULD do reverse if we reversed the dependencies (using cells below and right), which is what Dungeon Game does.
Question 3: What if the robot could ALSO move diagonally? How does our formula change?
Hint: How many ways can you now enter cell
(i,j)
?
Click for answer
dp[i][j] = dp[i-1][j] // from top
+ dp[i][j-1] // from left
+ dp[i-1][j-1]; // from diagonal
Now each cell has 3 incoming paths instead of 2!
For a 3ร3 grid with diagonal moves:
1 1 1
1 3 5
1 5 13
The center cell (1,1) now has 3 ways instead of 2!
๐ Key Takeawaysโ
-
The Recursive Insight:
paths(i,j) = paths(i-1,j) + paths(i,j-1)
- This is the foundation of the entire solution
-
Why Addition Works:
- Mutually exclusive events (can't come from both directions simultaneously)
- Exhaustive (covers all possibilities)
-
Three Implementation Levels:
- Recursion โ Simple but slow
- 2D DP โ Clear and standard
- 1D DP โ Space optimized
-
The Pattern Recognition:
- When you see "count paths in grid"
- Think: "build each cell from its dependencies"
-
Dependency Order Matters:
- Must fill in topological order
- Usually: left-to-right, top-to-bottom
๐ Next Stepsโ
After mastering Unique Paths, try these variations:
- Unique Paths II - Add obstacles
- Minimum Path Sum - Change from counting to optimization
- Dungeon Game - Reverse the direction!
- Triangle - Irregular grid structure
Each builds on the same core insight but adds one new complexity.
Remember: The best problem solvers don't just memorize solutions. They understand the discovery process that leads to the solution. This mental model will serve you for hundreds of similar problems.