π§± Linear DP: Building Solutions Step by Step
The Staircase Metaphor πͺ
Imagine youβre climbing a magical staircase. Each step you take builds on the ones before. You canβt jump to step 10 without first knowing how to reach step 9. This is Dynamic Programming β solving big problems by remembering small solutions!
π° The Fibonacci Pattern: Natureβs Building Blocks
What is Fibonacci?
Think of baby rabbits. Start with 1 pair. After a month, they have babies. Now you have 2 pairs. Next month, the first pair has more babies. Now 3 pairs. Then 5, then 8β¦
The Pattern:
1, 1, 2, 3, 5, 8, 13, 21...
Each number = sum of the previous two numbers!
Simple Example
// The magical formula
fib(5) = fib(4) + fib(3)
fib(4) = fib(3) + fib(2)
fib(3) = fib(2) + fib(1)
Itβs like asking βHow many rabbits at month 5?β You need to know month 4 and month 3 first!
The Smart Way (DP)
function fib(n) {
let prev = 0, curr = 1;
for (let i = 2; i <= n; i++) {
let next = prev + curr;
prev = curr;
curr = next;
}
return curr;
}
Why this works: We only remember the last two numbers. Like climbing stairs β you only need to remember the last two steps!
graph TD A["fib#40;5#41; = ?"] --> B["Need fib#40;4#41; + fib#40;3#41;"] B --> C["fib#40;4#41; = fib#40;3#41; + fib#40;2#41;"] B --> D["fib#40;3#41; = fib#40;2#41; + fib#40;1#41;"] C --> E["Build from bottom up!"] D --> E
πͺ Climbing Stairs: Your First DP Problem
The Story
Youβre a little frog πΈ at the bottom of a staircase with n steps. You can hop 1 step or 2 steps at a time. How many different ways can you reach the top?
Think Like a Frog
To reach step 5:
- Jump from step 4 (1 step hop)
- Jump from step 3 (2 step hop)
So: ways(5) = ways(4) + ways(3)
Sound familiar? Itβs Fibonacci!
Real Example
3 steps β 3 ways:
- 1 + 1 + 1 (hop, hop, hop)
- 1 + 2 (hop, leap)
- 2 + 1 (leap, hop)
The Code
function climbStairs(n) {
if (n <= 2) return n;
let prev = 1, curr = 2;
for (let i = 3; i <= n; i++) {
let next = prev + curr;
prev = curr;
curr = next;
}
return curr;
}
Why It Works
| Step | Ways | How? |
|---|---|---|
| 1 | 1 | Just hop once |
| 2 | 2 | (1+1) or (2) |
| 3 | 3 | ways(2) + ways(1) |
| 4 | 5 | ways(3) + ways(2) |
| 5 | 8 | ways(4) + ways(3) |
graph TD A["Step 5: 8 ways"] --> B["From Step 4: 5 ways"] A --> C["From Step 3: 3 ways"] B --> D["5 + 3 = 8 β"] C --> D
π House Robber: The Clever Thief
The Story
Youβre a sneaky raccoon π¦ on a street of houses. Each house has yummy treats inside. But thereβs a catch! If you visit two houses next to each other, the alarm goes off!
How do you get the MOST treats?
Think Like a Raccoon
At each house, you have 2 choices:
- Rob this house β Canβt rob the previous one
- Skip this house β Keep what you had
Real Example
Houses: [2, 7, 9, 3, 1]
| House | Value | Best Choice | Total |
|---|---|---|---|
| 1 | 2 | Take it | 2 |
| 2 | 7 | Take it (7 > 2) | 7 |
| 3 | 9 | Take + house 1 (2+9=11) | 11 |
| 4 | 3 | 11 > 7+3, skip | 11 |
| 5 | 1 | 11+1 or 11? Same! | 12 |
Answer: Rob houses 1, 3, 5 β 2 + 9 + 1 = 12
The Magic Formula
best(i) = max(
best(i-1), // skip this house
best(i-2) + value(i) // rob this house
)
The Code
function rob(nums) {
if (nums.length === 0) return 0;
if (nums.length === 1) return nums[0];
let prev2 = 0;
let prev1 = 0;
for (let num of nums) {
let curr = Math.max(
prev1, // skip
prev2 + num // rob
);
prev2 = prev1;
prev1 = curr;
}
return prev1;
}
graph TD A["At each house"] --> B{"Rob or Skip?"} B -->|Rob| C["Add value + skip neighbor"] B -->|Skip| D["Keep previous best"] C --> E["Pick the MAX"] D --> E
π Decode Ways: Secret Messages
The Story
Youβre a spy π΅οΈ receiving secret number codes. Each letter A-Z is coded as 1-26.
- A = 1, B = 2, C = 3 β¦ Z = 26
Given a string of numbers, how many ways can you decode it?
The Tricky Part
The code β12β could mean:
- β1β then β2β β A, B β βABβ
- β12β together β L β βLβ
2 ways to decode β12β!
Real Example
Code: β226β
| Reading | Letters | Valid? |
|---|---|---|
| 2-2-6 | B-B-F | β |
| 22-6 | V-F | β |
| 2-26 | B-Z | β |
Answer: 3 ways!
The Rules
- Single digit (1-9) β Valid letter
- Two digits (10-26) β Valid letter
- β0β alone β Invalid!
- β30β, β40β etc β Invalid!
Think Step by Step
At position i:
- Can we use 1 digit? Add
ways(i-1) - Can we use 2 digits? Add
ways(i-2)
The Code
function numDecodings(s) {
if (s[0] === '0') return 0;
let prev2 = 1; // empty string
let prev1 = 1; // first char
for (let i = 1; i < s.length; i++) {
let curr = 0;
// One digit decode
if (s[i] !== '0') {
curr += prev1;
}
// Two digit decode
let twoDigit = parseInt(s.slice(i-1, i+1));
if (twoDigit >= 10 && twoDigit <= 26) {
curr += prev2;
}
prev2 = prev1;
prev1 = curr;
}
return prev1;
}
Visual Guide
graph TD A["&#39;226&#39;"] --> B["2 β valid single"] A --> C["22 β valid pair"] B --> D["26 β valid pair"] B --> E["2,6 β valid singles"] C --> F["6 β valid single"] D --> G["Way 1: B-Z"] E --> H["Way 2: B-B-F"] F --> I["Way 3: V-F"]
π― The DP Pattern Summary
All four problems follow the same recipe:
The Recipe π³
- Find the subproblem β What smaller question helps answer the big one?
- Write the formula β How does today depend on yesterday?
- Remember only what you need β Usually just 1-2 previous values
- Build from the ground up β Start small, grow big
Side by Side
| Problem | Formula | We Remember |
|---|---|---|
| Fibonacci | f(n) = f(n-1) + f(n-2) | Last 2 numbers |
| Stairs | ways(n) = ways(n-1) + ways(n-2) | Last 2 counts |
| Robber | best(i) = max(skip, rob) | Last 2 bests |
| Decode | ways(i) = one_digit + two_digit | Last 2 ways |
π‘ The Big Idea
Dynamic Programming is just smart remembering!
Instead of solving the same thing over and over, we:
- Solve small problems first
- Write down the answers
- Use those answers to solve bigger problems
Itβs like leaving breadcrumbs π on your path β so you never get lost!
π You Got This!
These four problems are the foundation. Master them, and youβll see this pattern everywhere:
- Stock trading
- Coin change
- Text editing
- Path finding
Remember: Every expert was once a beginner standing at the bottom of the staircase. Now you know how to climb it β one step at a time! πͺβ¨
