Skip to content

Commit 4fb9f38

Browse files
committed
content(blog): unique paths
1 parent 7facedc commit 4fb9f38

File tree

2 files changed

+148
-3
lines changed

2 files changed

+148
-3
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
LeetCode 62, "Unique Paths," is a classic problem that often serves as an excellent introduction to dynamic programming. It challenges us to find the number of unique paths a robot can take to reach the bottom-right corner of a `m x n` grid, starting from the top-left corner. The robot can only move either down or right at any point in time.
2+
3+
## Problem Description
4+
5+
Imagine a robot positioned at the top-left cell (0,0) of a grid with `m` rows and `n` columns. The robot's goal is to reach the bottom-right cell (`m-1`, `n-1`). The only allowed moves are one step down or one step right. We need to calculate the total number of distinct paths the robot can take to reach its destination.
6+
7+
Let's visualize a simple `3 x 7` grid:
8+
9+
```
10+
S . . . . . .
11+
. . . . . . .
12+
. . . . . . F
13+
```
14+
15+
Where `S` is the start and `F` is the finish.
16+
17+
## Dynamic Programming Approach
18+
19+
This problem has optimal substructure and overlapping subproblems, making it a perfect candidate for dynamic programming.
20+
21+
Consider a cell `(i, j)` in the grid. To reach this cell, the robot must have come either from the cell directly above it (`i-1, j`) by moving down, or from the cell directly to its left (`i, j-1`) by moving right.
22+
23+
Therefore, the number of unique paths to reach `(i, j)` is the sum of unique paths to reach `(i-1, j)` and unique paths to reach `(i, j-1)`.
24+
25+
Let `dp[i][j]` represent the number of unique paths to reach cell `(i, j)`.
26+
The recurrence relation is:
27+
`dp[i][j] = dp[i-1][j] + dp[i][j-1]`
28+
29+
**Base Cases:**
30+
* For any cell in the first row (`i=0`), there's only one way to reach it: by moving right repeatedly from `(0,0)`. So, `dp[0][j] = 1`.
31+
* For any cell in the first column (`j=0`), there's only one way to reach it: by moving down repeatedly from `(0,0)`. So, `dp[i][0] = 1`.
32+
* The starting cell `(0,0)` has `dp[0][0] = 1` path (it's already there).
33+
34+
We can build a 2D array (or even optimize space to a 1D array) to store these path counts.
35+
36+
## Go Solution
37+
38+
Here's an implementation of the dynamic programming approach in Go:
39+
40+
```go
41+
func uniquePaths(m int, n int) int {
42+
// Create a 2D DP array initialized with 1s for the base cases
43+
dp := make([][]int, m)
44+
for i := range dp {
45+
dp[i] = make([]int, n)
46+
}
47+
48+
// Initialize the first row and first column with 1s
49+
// since there's only one way to reach any cell in the first row/column
50+
// (by only moving right or only moving down respectively).
51+
for i := 0; i < m; i++ {
52+
dp[i][0] = 1
53+
}
54+
for j := 0; j < n; j++ {
55+
dp[0][j] = 1
56+
}
57+
58+
// Fill the DP table
59+
for i := 1; i < m; i++ {
60+
for j := 1; j < n; j++ {
61+
dp[i][j] = dp[i-1][j] + dp[i][j-1]
62+
}
63+
}
64+
65+
// The result is the value at the bottom-right corner
66+
return dp[m-1][n-1]
67+
}
68+
```
69+
### Combinatorial Approach
70+
71+
Alternatively, this problem can be solved using a combinatorial approach. To reach the bottom-right corner of an `m x n` grid, the robot must make exactly `m-1` 'down' moves and `n-1` 'right' moves. The total number of moves will be `(m-1) + (n-1)`.
72+
73+
The problem then reduces to finding the number of ways to arrange these `m-1` down moves and `n-1` right moves. This is a classic combinatorial problem: choosing `m-1` positions for the 'down' moves (or `n-1` positions for the 'right' moves) out of a total of `(m-1) + (n-1)` moves.
74+
75+
The formula for combinations is C(N, K) = N! / (K! * (N-K)!), where N is the total number of steps and K is the number of 'down' (or 'right') moves.
76+
77+
### Go Solution (Combinatorial)
78+
79+
```go
80+
func uniquePathsCombinatorial(m int, n int) int {
81+
downMoves := m - 1
82+
rightMoves := n - 1
83+
totalSteps := downMoves + rightMoves
84+
85+
// Choose the smaller of downMoves or rightMoves for k to minimize calculations
86+
k := downMoves
87+
if rightMoves < downMoves {
88+
k = rightMoves
89+
}
90+
91+
var comb float64 = 1.0
92+
// Formula: C(N, K) = (N/1) * ((N-1)/2) * ... * ((N-k+1)/k)
93+
// This avoids large factorial calculations by performing multiplications and divisions iteratively.
94+
for i := 1; i <= k; i++ {
95+
comb = comb * float64(totalSteps - i + 1) / float64(i)
96+
}
97+
98+
return int(comb)
99+
}
100+
```
101+
102+
## Conclusion
103+
104+
The "Unique Paths" problem demonstrates the power of dynamic programming in breaking down a complex problem into simpler, overlapping subproblems. By carefully defining our state and recurrence relation, we can build up the solution efficiently. This particular problem also has a combinatorial solution using binomial coefficients, but the dynamic programming approach is often more intuitive for beginners to DP.

public/posts/posts.json

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@
55
"date": "2025-11-23",
66
"updated": "2025-11-23",
77
"description": "An explanation of Gaussian Elimination, a fundamental technique for solving linear systems, and its broad applications in computer engineering.",
8-
"tags": ["linear-algebra", "gaussian-elimination", "computer-engineering", "math", "algorithms"],
8+
"tags": [
9+
"linear-algebra",
10+
"gaussian-elimination",
11+
"computer-engineering",
12+
"math",
13+
"algorithms"
14+
],
915
"category": "dev",
1016
"filename": "gaussian-elimination.txt",
1117
"authors": ["fezcode"],
@@ -29,7 +35,13 @@
2935
"date": "2025-11-21",
3036
"updated": "2025-11-21",
3137
"description": "Dive into the quirky world of JavaScript's floating-point math, where 0.1 + 0.2 isn't always 0.3. Discover why and then ponder the mythical `====` operator, designed for complete equalness beyond your wildest dreams!",
32-
"tags": ["javascript", "floating-point", "precision", "ieee-754", "programming"],
38+
"tags": [
39+
"javascript",
40+
"floating-point",
41+
"precision",
42+
"ieee-754",
43+
"programming"
44+
],
3345
"category": "rant",
3446
"filename": "floating-point-precision-in-javascript.txt",
3547
"authors": ["fezcode"],
@@ -65,7 +77,17 @@
6577
"date": "2025-11-16",
6678
"updated": "2025-11-16",
6779
"description": "A deep dive into various BaseXX encoding methods, comparing their character sets, efficiency, and common use cases in modern computing.",
68-
"tags": ["encoding", "base32", "base58", "base62", "base64", "base85", "data-representation", "webdev", "cryptocurrency"],
80+
"tags": [
81+
"encoding",
82+
"base32",
83+
"base58",
84+
"base62",
85+
"base64",
86+
"base85",
87+
"data-representation",
88+
"webdev",
89+
"cryptocurrency"
90+
],
6991
"category": "dev",
7092
"filename": "decoding-the-digital-alphabet-base-xx-encodings.txt",
7193
"authors": ["fezcode"],
@@ -427,6 +449,25 @@
427449
"tags": ["cs", "algorithms", "graphs"],
428450
"series": {
429451
"posts": [
452+
{
453+
"slug": "leetcode-62-unique-paths",
454+
"title": "LeetCode 62: Unique Paths - A Dynamic Programming Approach",
455+
"date": "2025-11-24",
456+
"updated": "2025-11-24",
457+
"description": "Exploring LeetCode 62, Unique Paths, and solving it efficiently using dynamic programming in Go.",
458+
"tags": [
459+
"leetcode",
460+
"algorithms",
461+
"dynamic-programming",
462+
"go",
463+
"recursion",
464+
"combination"
465+
],
466+
"category": "dev",
467+
"filename": "/algos/leetcode-62-unique-paths.txt",
468+
"authors": ["fezcode"],
469+
"image": "/images/defaults/kaja-kadlecova-e04R6GDZdvY-unsplash.jpg"
470+
},
430471
{
431472
"slug": "minimum-number-of-steps-to-make-two-strings-anagram",
432473
"title": "Minimum Number of Steps to Make Two Strings Anagram",

0 commit comments

Comments
 (0)