Competitive Coding
Unit 4: Basic Dynamic Programming
From recursive brute force to elegant optimal solutions โ master the art of dynamic programming, solve classic problems, and ace coding interviews at top Indian tech companies.
โฑ๏ธ 8 hrs theory + 6 hrs practice | ๐ฐ Earning Potential: โน10,000โโน40,000/month | ๐ 30 MCQs (Bloom's Mapped)
๐ผ Jobs this unlocks: Competitive Programmer | SDE at FAANG/Product Cos (โน12โ40 LPA) | Algorithm Engineer
Opening Hook โ The Hidden Algorithm Behind Billions
๐ข How Paytm, Amazon & Google Use Dynamic Programming Every Second
Every time Paytm shows you a cashback offer, a dynamic programming algorithm is running behind the scenes. It evaluates thousands of possible offer combinations and picks the one that maximises your engagement while keeping Paytm's costs optimal. This isn't a simple if-else โ it's a variant of the classic Knapsack problem, one of the foundational DP problems you'll learn in this chapter.
Amazon's pricing engine uses DP to dynamically set prices across 10 crore+ products. When you see "โน499" instead of "โน599," a DP-based optimisation decided that price point maximises revenue across the entire product catalog. Google Maps finds the shortest route from your location to any destination using Dijkstra's algorithm โ which relies on the optimal substructure property, a core concept of DP.
What if YOU could solve these problems? What if you could look at a complex optimisation problem and say, "I know how to break this down"? That's exactly what this chapter teaches you โ the systematic art of Dynamic Programming.
Learning Outcomes โ Bloom's Taxonomy Mapped
| Bloom's Level | Learning Outcome |
|---|---|
| ๐ต Remember | Define dynamic programming and list its two key properties: overlapping subproblems and optimal substructure |
| ๐ต Remember | State the recurrence relations for Fibonacci, tiling, climbing stairs, and coin change problems |
| ๐ต Understand | Explain the difference between memoization (top-down) and tabulation (bottom-up) using Fibonacci as an example |
| ๐ต Understand | Illustrate why naive recursion for Fibonacci is O(2โฟ) while DP reduces it to O(n) |
| ๐ข Apply | Implement DP solutions for climbing stairs, coin change, and house robber problems in C/C++ |
| ๐ข Apply | Trace and fill DP tables for given inputs step-by-step |
| ๐ข Analyze | Compare time and space complexity of recursive vs memoized vs tabulated approaches |
| ๐ข Analyze | Identify whether a given problem exhibits optimal substructure and overlapping subproblems |
| ๐ Evaluate | Judge which DP technique (memoization vs tabulation) is better suited for a given problem scenario |
| ๐ Evaluate | Evaluate space optimisation opportunities in DP solutions (e.g., O(n) โ O(1)) |
| ๐ Create | Design DP solutions for unseen problems by identifying states, transitions, and base cases |
| ๐ Create | Formulate optimised DP solutions with reduced space complexity for classic problems |
Concept Explanation โ Dynamic Programming from Scratch
1. Introduction to Dynamic Programming
Dynamic Programming (DP) is an algorithmic technique that solves complex problems by breaking them into simpler overlapping subproblems and storing their solutions to avoid redundant computation. The term was coined by Richard Bellman in the 1950s.
When should you use DP? Two conditions must BOTH hold:
- Overlapping Subproblems โ The same subproblems are solved again and again during recursion.
- Optimal Substructure โ The optimal solution to the problem can be constructed from optimal solutions of its subproblems.
DP = Recursion + Memoization (top-down approach) OR Tabulation (bottom-up approach). Both avoid recomputing the same results.
๐ Fibonacci: The Gateway to DP
The Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, โฆ
Recurrence: F(n) = F(n-1) + F(n-2), with base cases F(0) = 0, F(1) = 1.
The naive recursive approach recomputes F(3) multiple times when computing F(5). DP stores each result once.
Naive Recursive Fibonacci (Slow โ O(2โฟ))
C++ // Naive recursive Fibonacci โ exponential time! int fib(int n) { if (n <= 1) return n; return fib(n - 1) + fib(n - 2); } // fib(5) makes 15 function calls! // fib(40) makes over 300 million calls!
DP Fibonacci โ Tabulation (Fast โ O(n))
C++ // DP Fibonacci โ linear time, linear space int fib(int n) { if (n <= 1) return n; int dp[n + 1]; dp[0] = 0; dp[1] = 1; for (int i = 2; i <= n; i++) dp[i] = dp[i - 1] + dp[i - 2]; return dp[n]; } // fib(40) now takes only 40 operations!
2. Tiling Problem
Problem: In how many ways can you fill a 2รn board with 2ร1 tiles?
Base cases:
n = 1: Only 1 way โ place one vertical tile.f(1) = 1n = 2: Two ways โ two vertical tiles OR two horizontal tiles.f(2) = 2
Recurrence: For a 2รn board, either place a vertical tile (leaving a 2ร(n-1) board) or place two horizontal tiles (leaving a 2ร(n-2) board).
f(n) = f(nโ1) + f(nโ2)
DP Table Trace for n = 6
| n | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| f(n) | 1 | 2 | 3 | 5 | 8 | 13 |
Trace: f(3)=f(2)+f(1)=2+1=3, f(4)=f(3)+f(2)=3+2=5, f(5)=f(4)+f(3)=5+3=8, f(6)=f(5)+f(4)=8+5=13.
C++ #include <iostream> using namespace std; int tilingWays(int n) { if (n <= 2) return n; int dp[n + 1]; dp[1] = 1; dp[2] = 2; for (int i = 3; i <= n; i++) dp[i] = dp[i - 1] + dp[i - 2]; return dp[n]; } int main() { int n; cout << "Enter n: "; cin >> n; cout << "Ways to tile 2x" << n << " board: " << tilingWays(n) << endl; return 0; }
3. Tabulation vs Memoization
Memoization (Top-Down): Start from the original problem, recurse downward, and cache results in a table so each subproblem is solved only once.
Tabulation (Bottom-Up): Start from the smallest subproblems (base cases), and iteratively build up to the final answer using a DP table.
| Parameter | Memoization (Top-Down) | Tabulation (Bottom-Up) |
|---|---|---|
| Approach | Recursive + lookup cache | Iterative + DP table |
| Starting Point | Main problem โ subproblems | Base case โ main problem |
| Table Filling | On demand (lazy evaluation) | All entries filled (eager) |
| Stack Overflow Risk | Yes (deep recursion for large n) | No (iterative loop) |
| Extra Stack Space | O(n) for recursion call stack | None |
| Code Style | More intuitive, natural | Typically more efficient |
Fibonacci โ Memoization (Top-Down)
C++ #include <iostream> #include <cstring> using namespace std; int memo[1001]; int fib(int n) { if (n <= 1) return n; if (memo[n] != -1) return memo[n]; // already computed! memo[n] = fib(n - 1) + fib(n - 2); return memo[n]; } int main() { memset(memo, -1, sizeof(memo)); cout << fib(6) << endl; // Output: 8 return 0; }
Fibonacci โ Tabulation (Bottom-Up)
C++ int fib(int n) { if (n <= 1) return n; int dp[n + 1]; dp[0] = 0; dp[1] = 1; for (int i = 2; i <= n; i++) dp[i] = dp[i - 1] + dp[i - 2]; return dp[n]; } // DP Table for fib(6): // i: 0 1 2 3 4 5 6 // dp[i]: 0 1 1 2 3 5 8
4. Optimal Substructure Property
Definition: A problem has optimal substructure if an optimal solution to the problem contains optimal solutions to its subproblems.
๐ When Does Optimal Substructure Hold?
โ Shortest Path (YES): The shortest path from A to C through B = shortest(AโB) + shortest(BโC). If you know the shortest path to each intermediate point, you can combine them.
โ Fibonacci (YES): F(n) = F(n-1) + F(n-2). Each subproblem contributes optimally to the final answer.
โ Coin Change (YES): Minimum coins for amount n = 1 + minimum coins for (n โ coin_value). The subproblem's optimal feeds the parent's optimal.
โ Longest Simple Path (NO): In a general graph with no repeated vertices, combining the longest path from AโB and BโC may create cycles. The subproblems interfere with each other.
5. Overlapping Subproblems Property
Definition: A problem has overlapping subproblems when the same subproblems are solved again and again during recursion.
Fibonacci Recursion Tree for F(5)
Tree
F(5)
/ \
F(4) F(3) โ F(3) computed here
/ \ / \
F(3) F(2) F(2) F(1) โ F(3) also here! F(2) repeated!
/ \
F(2) F(1) โ F(2) again!
F(3) is computed 2 times
F(2) is computed 3 times
F(1) is computed 5 times
Total function calls for F(5): 15 calls!
Why naive recursion is O(2โฟ): The recursion tree is a binary tree. At each level, the number of calls roughly doubles. For F(n), there are approximately 2โฟ total calls.
Why DP makes it O(n): With memoization or tabulation, each value F(0) through F(n) is computed exactly once and stored. Total work = n computations.
6. Dynamic Programming Process and Techniques
๐ ๏ธ The 5-Step DP Framework
Step 1 โ Define State: What does dp[i] represent? This is the most critical step. Example: dp[i] = minimum coins needed to make amount i.
Step 2 โ Write Recurrence Relation: How does dp[i] relate to previous states? Example: dp[i] = min(dp[i - coin] + 1) for all valid coins.
Step 3 โ Identify Base Cases: What are the trivial/smallest answers? Example: dp[0] = 0 (zero coins needed for amount 0).
Step 4 โ Decide Iteration Order: Left to right? Bottom-up in a grid? This depends on which states your current state depends on. For coin change: iterate i from 1 to amount.
Step 5 โ Optimise Space if Possible: Can you reduce O(n) space to O(1)? For Fibonacci, you only need the last 2 values, not the entire array.
Applying the Framework: Fibonacci
- State:
dp[i]= the i-th Fibonacci number - Recurrence:
dp[i] = dp[i-1] + dp[i-2] - Base cases:
dp[0] = 0,dp[1] = 1 - Iteration order: Left to right (i = 2, 3, โฆ, n)
- Space optimisation: Only need
prev2andprev1โ O(1) space
Applying the Framework: Climbing Stairs
- State:
dp[i]= number of ways to reach stairi - Recurrence:
dp[i] = dp[i-1] + dp[i-2](reach stair i from i-1 by 1 step, or from i-2 by 2 steps) - Base cases:
dp[0] = 1(1 way to stay at ground),dp[1] = 1 - Iteration order: Left to right (i = 2 to n)
- Space optimisation: Same as Fibonacci โ O(1) possible
7. Formulating DP Problems
"Is This a DP Problem?" โ Checklist
- โ Does the problem ask for optimal (min/max) or count of ways?
- โ Can I make a choice at each step (take/skip, include/exclude)?
- โ Does the problem have overlapping subproblems?
- โ Does it have optimal substructure?
- โ Can I define a state that captures the essential information?
If you answer YES to most of these, it's likely a DP problem.
Common DP Patterns
| Pattern | Description | Classic Examples |
|---|---|---|
| Linear DP | 1D array, dp[i] depends on previous elements | Fibonacci, Climbing Stairs, House Robber |
| Grid DP | 2D array, dp[i][j] depends on adjacent cells | Min Cost Path, Unique Paths |
| Interval DP | dp[i][j] = optimal for subarray [i..j] | Matrix Chain Multiplication |
| Tree DP | DP computed on tree nodes (children โ parent) | Diameter of tree, subtree sums |
| Bitmask DP | States encoded as bitmasks for subset tracking | Travelling Salesman Problem |
8. Classic DP Examples
8.1 โ Climbing Stairs
Problem: You can climb 1 or 2 stairs at a time. How many distinct ways to reach the top of n stairs?
State: dp[i] = number of distinct ways to reach stair i.
Recurrence: dp[i] = dp[i-1] + dp[i-2]
Base cases: dp[0] = 1, dp[1] = 1
DP Table Trace for n = 5
| i | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|
| dp[i] | 1 | 1 | 2 | 3 | 5 | 8 |
dp[2]=dp[1]+dp[0]=1+1=2. dp[3]=dp[2]+dp[1]=2+1=3. dp[4]=dp[3]+dp[2]=3+2=5. dp[5]=dp[4]+dp[3]=5+3=8.
C++ #include <iostream> using namespace std; int climbStairs(int n) { if (n <= 1) return 1; int dp[n + 1]; dp[0] = 1; dp[1] = 1; for (int i = 2; i <= n; i++) dp[i] = dp[i - 1] + dp[i - 2]; return dp[n]; } int main() { cout << "Ways to climb 5 stairs: " << climbStairs(5) << endl; // Output: 8 return 0; }
Time: O(n) Space: O(n) โ can optimise to O(1) using two variables.
8.2 โ Coin Change (Minimum Coins)
Problem: Given coins of certain denominations, find the minimum number of coins to make a given amount.
State: dp[i] = minimum coins to make amount i.
Recurrence: dp[i] = min(dp[i - coin] + 1) for all coins where coin โค i
Base case: dp[0] = 0 (zero coins for amount 0)
DP Table Trace: amount = 11, coins = {1, 5, 6}
| i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| dp[i] | 0 | 1 | 2 | 3 | 4 | 1 | 1 | 2 | 3 | 4 | 2 | 2 |
Trace for dp[11]: dp[11] = min(dp[10]+1, dp[6]+1, dp[5]+1) = min(3, 2, 2) = 2. Solution: use coins 5 + 6 = 11.
C++ #include <iostream> #include <vector> #include <climits> using namespace std; int coinChange(vector<int>& coins, int amount) { vector<int> dp(amount + 1, INT_MAX); dp[0] = 0; for (int i = 1; i <= amount; i++) { for (int coin : coins) { if (coin <= i && dp[i - coin] != INT_MAX) dp[i] = min(dp[i], dp[i - coin] + 1); } } return dp[amount] == INT_MAX ? -1 : dp[amount]; } int main() { vector<int> coins = {1, 5, 6}; cout << "Min coins for 11: " << coinChange(coins, 11) << endl; // Output: 2 return 0; }
Time: O(amount ร |coins|) Space: O(amount)
8.3 โ House Robber
Problem: You're a robber planning to rob houses along a street. You cannot rob two adjacent houses (alarm triggers). Maximise the total loot.
State: dp[i] = maximum money by considering houses 0 to i.
Recurrence: dp[i] = max(dp[i-1], dp[i-2] + money[i])
Base cases: dp[0] = money[0], dp[1] = max(money[0], money[1])
DP Table Trace: houses = {2, 7, 9, 3, 1}
| i | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| money[i] | 2 | 7 | 9 | 3 | 1 |
| dp[i] | 2 | 7 | 11 | 11 | 12 |
dp[0]=2. dp[1]=max(2,7)=7. dp[2]=max(7, 2+9)=11. dp[3]=max(11, 7+3)=11. dp[4]=max(11, 11+1)=12. Rob houses 0, 2, 4 (โน2+โน9+โน1=โน12).
C++ #include <iostream> #include <vector> #include <algorithm> using namespace std; int houseRobber(vector<int>& money) { int n = money.size(); if (n == 0) return 0; if (n == 1) return money[0]; vector<int> dp(n); dp[0] = money[0]; dp[1] = max(money[0], money[1]); for (int i = 2; i < n; i++) dp[i] = max(dp[i - 1], dp[i - 2] + money[i]); return dp[n - 1]; } int main() { vector<int> houses = {2, 7, 9, 3, 1}; cout << "Max loot: " << houseRobber(houses) << endl; // Output: 12 return 0; }
Time: O(n) Space: O(n) โ can optimise to O(1) with two variables.
8.4 โ Min Cost Path in Grid
Problem: Given an mรn grid where each cell has a cost, find the path from top-left to bottom-right with minimum total cost. You can only move right or down.
State: dp[i][j] = minimum cost to reach cell (i, j).
Recurrence: dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])
Base cases: dp[0][0] = grid[0][0]. First row and first column are cumulative sums.
DP Table Trace: grid = {{1,3,1},{1,5,1},{4,2,1}}
| j=0 | j=1 | j=2 | |
|---|---|---|---|
| i=0 | 1 | 4 | 5 |
| i=1 | 2 | 7 | 6 |
| i=2 | 6 | 8 | 7 |
dp[0][1]=1+3=4, dp[0][2]=4+1=5. dp[1][0]=1+1=2, dp[1][1]=5+min(4,2)=7, dp[1][2]=1+min(5,7)=6. dp[2][0]=4+2=6, dp[2][1]=2+min(7,6)=8, dp[2][2]=1+min(6,8)=7. Path: 1โ3โ1โ1โ1.
C++ #include <iostream> #include <vector> #include <algorithm> using namespace std; int minCostPath(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); vector<vector<int>> dp(m, vector<int>(n)); dp[0][0] = grid[0][0]; // Fill first row for (int j = 1; j < n; j++) dp[0][j] = dp[0][j - 1] + grid[0][j]; // Fill first column for (int i = 1; i < m; i++) dp[i][0] = dp[i - 1][0] + grid[i][0]; // Fill rest of DP table for (int i = 1; i < m; i++) for (int j = 1; j < n; j++) dp[i][j] = grid[i][j] + min(dp[i - 1][j], dp[i][j - 1]); return dp[m - 1][n - 1]; } int main() { vector<vector<int>> grid = {{1,3,1},{1,5,1},{4,2,1}}; cout << "Min cost: " << minCostPath(grid) << endl; // Output: 7 return 0; }
Time: O(mรn) Space: O(mรn) โ can optimise to O(n) by reusing a single row.
Learn by Doing โ 3-Tier Lab Structure
๐ข Tier 1 โ GUIDED TASK: Fibonacci & Climbing Stairs
Task A: Fibonacci Sequence
Step 1: Write a naive recursive Fibonacci function. Test for n=10, 20, 30, 40. Notice how n=40 takes several seconds.
Step 2: Now add a memo array (initialise to -1). Before computing, check if memo[n] != -1. If so, return cached result.
Step 3: Write a tabulation (bottom-up) version using a for loop and array.
Step 4: Print the first 20 Fibonacci numbers using your DP solution.
Step 5: Compare execution time: Use clock() to measure naive vs DP for n=40.
Task B: Climbing Stairs
Step 1: Implement the climbing stairs DP solution.
Step 2: Test for n=10, 20, 30. Print the complete DP table.
Step 3: Modify to also work for 1, 2, or 3 steps at a time. How does the recurrence change?
๐ก Tier 2 โ SEMI-GUIDED: Coin Change & Tiling
Task A: Coin Change with Indian Denominations
Mission: Given coins {1, 2, 5, 10}, find minimum coins needed for every amount from 1 to 100. Print which amounts need the most coins.
Hints:
- State:
dp[i]= minimum coins for amounti - Initialise dp[0] = 0, everything else = INT_MAX
- For each amount, try all 4 coins. Take minimum.
- Print the amount that requires the maximum number of coins.
Task B: Extended Tiling Problem
Mission: The classic 2รn tiling uses only 2ร1 tiles. Now also allow 2ร2 tiles. How does the recurrence change?
Hint: f(n) = f(n-1) + f(n-2) + f(n-2) = f(n-1) + 2ยทf(n-2). Think about what new configurations the 2ร2 tile enables.
int? Use long long.
๐ด Tier 3 โ OPEN CHALLENGE: Min Cost Path Visualiser
The Brief:
Given a 10ร10 grid with random costs (1โ9), find the minimum cost path from top-left to bottom-right and print the actual path (not just the cost). Visualise the grid with the optimal path marked using asterisks (*).
Requirements:
- Generate a 10ร10 grid with random values 1โ9
- Apply min-cost-path DP to find the cost
- Backtrack from (9,9) to (0,0) to recover the path
- Print the grid with path cells marked as
* - Print the total cost and the path coordinates
Problem Set โ Practice & Mastery
Part 1: DP Table Tracing (5 Problems)
Fill in the complete DP table for each problem. Show your work step-by-step.
T1. Fill the DP table for Fibonacci(8)
| i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| dp[i] | 0 | 1 | ? | ? | ? | ? | ? | ? | ? |
T2. Fill the DP table for Climbing Stairs(7)
| i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| dp[i] | 1 | 1 | ? | ? | ? | ? | ? | ? |
T3. Fill the DP table for Coin Change: amount=15, coins={1,5,10}
| i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| dp[i] | 0 | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
T4. Fill the DP table for House Robber: houses = {3, 1, 4, 1, 5, 9}
| i | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|
| money[i] | 3 | 1 | 4 | 1 | 5 | 9 |
| dp[i] | ? | ? | ? | ? | ? | ? |
T5. Fill the DP table for Min Cost Path: grid = {{2,1,3},{6,5,4},{7,8,9}}
| j=0 | j=1 | j=2 | |
|---|---|---|---|
| i=0 | ? | ? | ? |
| i=1 | ? | ? | ? |
| i=2 | ? | ? | ? |
Part 2: Programming Problems (8 Problems)
Implement each in C/C++. Provide time and space complexity.
- P1. Fibonacci N-th Term โ Compute the n-th Fibonacci number using tabulation. Beginner
- P2. Extended Climbing Stairs โ Count ways to climb n stairs with steps of 1, 2, or 3 at a time. Beginner
- P3. Coin Change (Min Coins) โ Given denominations and an amount, find minimum coins needed. Intermediate
- P4. House Robber (Circular) โ Houses are arranged in a circle (first and last are adjacent). Find max loot. Intermediate
- P5. Min Cost Path with Obstacles โ Same as min cost path, but some cells are blocked (cost = -1). Intermediate
- P6. Longest Increasing Subsequence โ Find the length of the LIS in an array. Intermediate
- P7. 0/1 Knapsack Problem โ Given weights and values, maximise value within weight capacity. Advanced
- P8. Edit Distance โ Find minimum operations (insert, delete, replace) to convert one string to another. Advanced
Part 3: Industry Application Problems (3 Problems)
- I1. Paytm Cashback Optimiser: Given N cashback offers, each with a value and a set of conflicting offers (can't use together), find the maximum total cashback a user can redeem. (Variant of weighted independent set / knapsack.)
- I2. Amazon Delivery Route: A city is represented as an mรn grid. Each cell has a fuel cost. Some cells are blocked (construction). Find the minimum fuel cost route from the warehouse (0,0) to the customer (m-1, n-1).
- I3. Flipkart Warehouse Allocation: Flipkart has K warehouses, each with a storage cost per unit. N products need to be stored. Minimise total storage cost such that no warehouse exceeds capacity. (Variant of bin packing / knapsack.)
Part 4: Interview Problems (3 Problems)
- V1. Google โ Maximum Subarray Sum: Given an integer array, find the contiguous subarray with the largest sum. Implement Kadane's algorithm as a DP solution. State:
dp[i]= max subarray sum ending at index i. - V2. Amazon โ Word Break: Given a string and a dictionary of words, determine if the string can be segmented into space-separated sequence of dictionary words. State:
dp[i]= true if s[0..i-1] can be segmented. - V3. Microsoft โ Decode Ways: Given a string of digits, count the number of ways to decode it (A=1, B=2, โฆ, Z=26). State:
dp[i]= number of ways to decode s[0..i-1].
MCQ Assessment Bank โ 30 Questions (Bloom's Mapped)
Remember / Identify (Q1โQ5)
Which two properties must a problem have for Dynamic Programming to be applicable?
- Greedy choice + divide and conquer
- Overlapping subproblems + optimal substructure
- Recursion + binary search
- Sorting + searching
What is the time complexity of the naive recursive Fibonacci algorithm?
- O(n)
- O(nยฒ)
- O(2โฟ)
- O(log n)
In memoization, computed results are stored in a ___.
- Binary search tree
- Lookup table or array
- Stack
- Queue
For the tiling problem f(n) = f(n-1) + f(n-2), the base cases are:
- f(0) = 0, f(1) = 0
- f(1) = 1, f(2) = 2
- f(1) = 2, f(2) = 1
- f(0) = 1, f(1) = 2
Tabulation is also known as the ___ approach.
- Top-down
- Divide and conquer
- Bottom-up
- Backtracking
Understand / Explain (Q6โQ10)
Why does the naive recursive Fibonacci have exponential time complexity?
- It uses too much memory
- The same subproblems are computed repeatedly, leading to a binary tree of calls
- Fibonacci numbers grow exponentially
- It uses division which is slow
Which DP approach fills the table entries "on demand" (lazily)?
- Tabulation
- Memoization
- Greedy
- Brute force
Why doesn't the "longest simple path" problem in a general graph have optimal substructure?
- Because graphs can't have paths
- Because combining longest sub-paths may reuse vertices, creating invalid (non-simple) paths
- Because the longest path is always unique
- Because graphs are always trees
In the climbing stairs problem, dp[4] = dp[3] + dp[2] because:
- We always climb 4 steps at once
- We can reach stair 4 either from stair 3 (1 step) or from stair 2 (2 steps)
- dp[4] is the sum of all previous values
- The problem requires sorting
Which DP approach is more prone to stack overflow for very large inputs?
- Tabulation (bottom-up)
- Memoization (top-down)
- Both are equally prone
- Neither can cause stack overflow
Apply (Q11โQ15)
Using the tabulation approach, what is fib(6)?
- 5
- 6
- 8
- 13
Coin change with coins={1,3,4}, amount=6. What is dp[6]?
- 1
- 2
- 3
- 6
House Robber with houses = {6, 7, 1, 30}. Maximum loot?
- 30
- 36
- 37
- 7
For climbing stairs, what is dp[3]? (dp[0]=1, dp[1]=1)
- 2
- 3
- 4
- 5
Min cost path, grid={{1,2},{3,4}}. What is dp[1][1]?
- 4
- 7
- 8
- 10
Analyze (Q16โQ20)
For computing Fibonacci(1000), which approach is safer?
- Memoization โ it's more intuitive
- Tabulation โ it avoids stack overflow from deep recursion
- Naive recursion โ it's simpler code
- Both are equally safe
A function makes calls f(n-1) and f(n/2). Does it have overlapping subproblems?
- No โ the subproblems are always different
- Yes โ values like f(1), f(2) will be reached via multiple paths
- Only if n is even
- Cannot be determined
Solution A: O(nยฒ) time, O(n) space. Solution B: O(n log n) time, O(nยฒ) space. For n=10โถ, which is better?
- Solution A โ less space
- Solution B โ faster execution time
- Both are equivalent
- Neither will work
In House Robber, why can't we use a greedy approach (always pick the largest)?
- Greedy always works for this problem
- Picking the largest may block two adjacent high-value houses โ e.g., {1, 100, 1, 100}
- Greedy is faster than DP
- DP can't solve this problem
Compare Fibonacci(5) recursion tree vs Binary Search on 32 elements. Which has overlapping subproblems?
- Both have overlapping subproblems
- Only Fibonacci โ Binary Search explores unique sub-arrays each time
- Only Binary Search
- Neither has overlapping subproblems
Evaluate (Q21โQ25)
A student writes dp[i] = dp[i-1] + dp[i-3] for climbing stairs (1 or 2 steps). What's wrong?
- Nothing โ it's correct
- Should be dp[i-1] + dp[i-2], since you can take 1 or 2 steps, not 1 or 3
- Should be dp[i-2] + dp[i-3]
- Should be dp[i-1] ร dp[i-2]
A student optimises Fibonacci by using only 2 variables instead of an array. Does this sacrifice correctness?
- Yes โ we lose information needed for the answer
- No โ we only ever need the last two values, so this is valid O(1) space optimisation
- It works for small n but fails for large n
- It changes the time complexity to O(nยฒ)
A student claims: "All recursive problems can be solved with DP." Is this correct?
- Yes โ recursion and DP are the same thing
- No โ DP only applies when there are overlapping subproblems and optimal substructure
- Yes โ just add memoization to any recursion
- No โ DP can only solve math problems
For coin change with coins={1,5,10,25}, is the greedy approach (always pick the largest coin) always optimal?
- Yes โ and this is true for all coin systems
- Yes โ for this specific set, greedy works. But it fails for sets like {1,3,4}
- No โ greedy never works for coin change
- No โ only DP works for any coin problem
Is it worth converting an O(n) space DP solution to O(1) space if n is always less than 100?
- Absolutely โ every optimisation matters
- Probably not โ the space saved is negligible and the code becomes less readable
- Yes โ it changes the time complexity too
- No โ O(1) space is impossible for DP
Create (Q26โQ30)
Write the recurrence for: Minimum cost to paint n houses with 3 colours (R, G, B), where no two adjacent houses can have the same colour. cost[i][c] = cost to paint house i with colour c.
- dp[i][c] = cost[i][c] + min(dp[i-1][other colours])
- dp[i][c] = cost[i][c] + dp[i-1][c]
- dp[i][c] = min(cost[i][0], cost[i][1], cost[i][2])
- dp[i] = cost[i] + dp[i-2]
Design the state definition for: Maximum profit from stock prices with at most 2 transactions.
- dp[i] = max profit on day i
- dp[i][j][k] where i=day, j=transactions used, k=holding/not-holding stock
- dp[i] = prices[i] - prices[0]
- dp[i][j] = profit using j stocks on day i
Max sum of non-adjacent elements in a circular array. How to handle the circular constraint?
- Run House Robber once on the full array
- Run House Robber twice: once on arr[0..n-2], once on arr[1..n-1], take the maximum
- Sort the array first, then apply House Robber
- Use a 2D DP table
Create a space-optimised climbing stairs solution using only 2 variables. Which code is correct?
prev=1; curr=1; for i=2..n: next=curr+prev; prev=curr; curr=next;a=0; b=1; for i=0..n: a=a+b;x=1; for i=0..n: x=2*x;a=1; b=1; for i=2..n: a=a+b; swap(a,b);
Design DP for: Count the number of ways to make change for amount n with given coins (not minimum, but count of combinations). What's the recurrence?
- dp[i] = dp[i-1] + dp[i-2]
- dp[i] += dp[i - coin] for each coin (process coins in outer loop to avoid counting permutations)
- dp[i] = min(dp[i-coin]+1)
- dp[i][j] = dp[i-1][j] + dp[i][j-1]
Short Answer Questions (8 Questions)
Q1. Define dynamic programming in your own words. What two properties must a problem have for DP to apply? (4 marks)
Answer: Dynamic Programming is an algorithmic paradigm that solves complex optimisation or counting problems by breaking them into smaller overlapping subproblems, solving each subproblem only once, and storing the result to avoid redundant computation. The two essential properties are:
1. Overlapping Subproblems: The problem can be broken into subproblems which are reused multiple times. Example: Fibonacci โ F(3) is needed by both F(5) and F(4).
2. Optimal Substructure: The optimal solution to the overall problem can be constructed from optimal solutions to its subproblems. Example: Shortest path โ the shortest path from A to C through B combines the shortest paths AโB and BโC.
Q2. Write the recurrence relation and base cases for the tiling problem (2รn board, 2ร1 tiles). Trace the DP table for n=7. (5 marks)
Recurrence: f(n) = f(n-1) + f(n-2)
Base Cases: f(1) = 1, f(2) = 2
Logic: For a 2รn board, either place a vertical tile (leaving 2ร(n-1)) or two horizontal tiles (leaving 2ร(n-2)).
DP Table for n=7:
| n | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|
| f(n) | 1 | 2 | 3 | 5 | 8 | 13 | 21 |
f(3)=2+1=3, f(4)=3+2=5, f(5)=5+3=8, f(6)=8+5=13, f(7)=13+8=21.
Q3. Compare memoization and tabulation with at least 5 differences. Which would you prefer for 10โต states? (5 marks)
| Parameter | Memoization | Tabulation |
|---|---|---|
| Direction | Top-down (problem โ subproblems) | Bottom-up (base โ answer) |
| Implementation | Recursive + lookup cache | Iterative + DP array |
| Table filling | Lazy โ only needed entries | Eager โ all entries filled |
| Stack overflow | Risk for large n | No risk (iterative) |
| Extra space | O(n) recursion stack | No extra stack space |
For 10โต states: Prefer tabulation. Recursion depth of 10โต will likely cause stack overflow. Tabulation handles this safely with a simple loop.
Q4. Draw the recursion tree for Fibonacci(5). Circle repeated subproblems. How many calls without DP vs with DP? (5 marks)
F(5)
/ \
F(4) F(3) โ REPEATED
/ \ / \
F(3) F(2) F(2) F(1) โ F(2) REPEATED
/ \
F(2) F(1) โ F(2) REPEATED
Without DP: 15 total function calls. F(2) computed 3 times, F(3) computed 2 times.
With DP (memoization): Only 9 calls (5 unique values + 4 cache hits). With tabulation: exactly 6 operations (fill dp[0] through dp[5]).
Q5. Explain the 5-step DP framework with the coin change example: coins={1,5,10}, amount=12. (6 marks)
Step 1 โ Define State: dp[i] = minimum number of coins to make amount i.
Step 2 โ Recurrence: dp[i] = min(dp[i-1]+1, dp[i-5]+1, dp[i-10]+1) for valid indices.
Step 3 โ Base Case: dp[0] = 0 (zero coins for zero amount).
Step 4 โ Iteration Order: Left to right, i from 1 to 12.
Step 5 โ Space Optimisation: Cannot easily optimise here since dp[i] depends on dp[i-1], dp[i-5], dp[i-10] โ need the full array.
Answer: dp[12] = min(dp[11]+1, dp[7]+1, dp[2]+1) = min(3, 3, 3) = 3 coins. Solution: 10+1+1 = 12.
Q6. What is optimal substructure? Give one example where it holds and one where it doesn't. (4 marks)
Definition: A problem has optimal substructure if the optimal solution contains optimal solutions to its subproblems.
Holds โ Shortest Path: The shortest path from A to C passing through B = shortest(AโB) + shortest(BโC). The subproblem solutions combine correctly.
Doesn't Hold โ Longest Simple Path: In a general graph, combining the longest simple path AโB and BโC may create cycles (revisit vertices), giving an invalid result. The subproblems interfere.
Q7. Solve House Robber for {2, 7, 9, 3, 1}. Show DP table and trace which houses are robbed. (5 marks)
| i | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| money[i] | 2 | 7 | 9 | 3 | 1 |
| dp[i] | 2 | 7 | 11 | 11 | 12 |
dp[0]=2, dp[1]=max(2,7)=7, dp[2]=max(7,2+9)=11, dp[3]=max(11,7+3)=11, dp[4]=max(11,11+1)=12.
Backtrack: dp[4]=12=dp[2]+money[4]=11+1 โ rob house 4. dp[2]=11=dp[0]+money[2]=2+9 โ rob house 2. dp[0]=2=money[0] โ rob house 0.
Houses robbed: 0, 2, 4 (values: 2+9+1 = 12).
Q8. Explain why greedy fails for coin change with coins={1,3,4} and amount=6, but DP gives the correct answer. (4 marks)
Greedy approach: Always pick the largest coin first. For amount=6: pick 4 (remaining=2), pick 1 (remaining=1), pick 1 (remaining=0). Total: 3 coins (4+1+1).
DP approach: dp[6] = min(dp[5]+1, dp[3]+1, dp[2]+1) = min(2+1, 1+1, 2+1) = 2 coins (3+3=6).
Why greedy fails: Greedy makes locally optimal choices (pick largest coin) but misses the globally optimal combination. By picking 4 first, it commits to a path that requires 3 coins. DP explores all possibilities and finds that two 3s is better. Greedy doesn't "look ahead" โ DP does.
Long Answer Questions (3 Questions)
Q1. Dynamic Programming Comprehensive (10 marks)
(a) Define DP and explain both properties with examples. (3 marks)
Dynamic Programming is an algorithmic technique for solving optimisation and counting problems by breaking them into overlapping subproblems and storing solutions to avoid recomputation.
Overlapping Subproblems: Same sub-computations recur. In Fibonacci, F(3) is needed by both F(5) and F(4).
Optimal Substructure: Optimal answer = combination of optimal sub-answers. In coin change, min coins for amount 11 = 1 + min coins for (11 โ coin).
(b) Solve Coin Change for coins={1,5,6,9}, amount=11. Show DP table, trace, write code. (4 marks)
| i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| dp[i] | 0 | 1 | 2 | 3 | 4 | 1 | 1 | 2 | 3 | 1 | 2 | 2 |
dp[11] = min(dp[10]+1, dp[6]+1, dp[5]+1, dp[2]+1) = min(3, 2, 2, 3) = 2. Use coins 5+6 or 9+? โ Actually dp[2]+1=3 (coin 9: dp[11-9]=dp[2]=2, so 2+1=3). dp[5]+1=1+1=2, dp[6]+1=1+1=2. Solution: 5+6=11 (2 coins).
C++ #include <iostream> #include <vector> #include <climits> using namespace std; int main() { vector<int> coins = {1,5,6,9}; int amount = 11; vector<int> dp(amount+1, INT_MAX); dp[0] = 0; for(int i=1; i<=amount; i++) for(int c : coins) if(c<=i && dp[i-c]!=INT_MAX) dp[i] = min(dp[i], dp[i-c]+1); cout << dp[amount] << endl; // Output: 2 }
(c) Optimise space complexity and explain trade-offs. (3 marks)
The coin change DP already uses O(amount) space, which is optimal for this problem โ we cannot reduce it further because dp[i] depends on dp[i-coin] where coin can be any denomination (not just the last 1โ2 values). Unlike Fibonacci where O(1) space works, coin change needs the full array. The trade-off: we sacrifice the ability to recover which coins were used (for that, we'd need an additional parent array).
Q2. DP Problem Solving โ Min Cost Path (10 marks)
(a) Explain the 5-step DP framework. (2 marks)
1. Define state (what dp[i][j] means). 2. Write recurrence. 3. Set base cases. 4. Decide iteration order. 5. Optimise space if possible.
(b) Apply to a 4ร4 grid. Show complete DP table. (4 marks)
Grid: {{1,3,5,8},{4,2,1,7},{4,3,2,3},{3,6,5,2}}
State: dp[i][j] = min cost to reach (i,j). Recurrence: dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1]).
| j=0 | j=1 | j=2 | j=3 | |
|---|---|---|---|---|
| i=0 | 1 | 4 | 9 | 17 |
| i=1 | 5 | 6 | 7 | 14 |
| i=2 | 9 | 9 | 9 | 12 |
| i=3 | 12 | 15 | 14 | 14 |
Answer: dp[3][3] = 14.
(c) Print the actual path using backtracking. (4 marks)
C++ // After building DP table, backtrack from (m-1,n-1) to (0,0) void printPath(vector<vector<int>>& dp, int m, int n) { vector<pair<int,int>> path; int i = m-1, j = n-1; path.push_back({i, j}); while (i > 0 || j > 0) { if (i == 0) j--; else if (j == 0) i--; else if (dp[i-1][j] < dp[i][j-1]) i--; else j--; path.push_back({i, j}); } for (int k = path.size()-1; k >= 0; k--) cout << "(" << path[k].first << "," << path[k].second << ") "; }
Q3. Comparative Analysis โ Fibonacci Three Ways (10 marks)
(a) Code for all three approaches. (4 marks)
C++ // 1. Recursive int fibRec(int n) { if(n<=1) return n; return fibRec(n-1) + fibRec(n-2); } // 2. Memoized int memo[1000001]; int fibMemo(int n) { if(n<=1) return n; if(memo[n]!=-1) return memo[n]; return memo[n] = fibMemo(n-1) + fibMemo(n-2); } // 3. Tabulated int fibTab(int n) { if(n<=1) return n; int dp[n+1]; dp[0]=0; dp[1]=1; for(int i=2;i<=n;i++) dp[i]=dp[i-1]+dp[i-2]; return dp[n]; }
(b) Comparison table. (3 marks)
| Approach | Time | Space | Stack Safe? |
|---|---|---|---|
| Recursive | O(2โฟ) | O(n) stack | No (stack overflow for n>30) |
| Memoized | O(n) | O(n) array + O(n) stack | No (stack overflow for n>10โด) |
| Tabulated | O(n) | O(n) array | Yes |
(c) For n=10โถ, use tabulation with O(1) space. (3 marks)
C++ long long fibOpt(int n) { if(n<=1) return n; long long prev2 = 0, prev1 = 1, curr; for(int i=2; i<=n; i++) { curr = prev1 + prev2; prev2 = prev1; prev1 = curr; } return prev1; }
This is O(n) time, O(1) space. Safe for n=10โถ. Note: actual Fibonacci values overflow even long long around n=93, so for very large n you'd need big-integer arithmetic or compute modulo a prime.
Lab Program โ Tiling Problem
๐ฌ Lab Program: Tiling Problem (2รn board with 2ร1 tiles)
Problem Statement
Given a 2รn board, find the number of ways to fill it completely using 2ร1 tiles. Tiles can be placed horizontally or vertically.
Algorithm
- Define
dp[i]= number of ways to tile a 2รi board. - Base cases:
dp[1] = 1,dp[2] = 2. - Recurrence:
dp[i] = dp[i-1] + dp[i-2]for i โฅ 3. - Iterate from i=3 to n, filling the DP table.
- Return
dp[n].
Complete Code
C++ #include <iostream> using namespace std; int tilingWays(int n) { if (n == 1) return 1; if (n == 2) return 2; int dp[n + 1]; dp[1] = 1; dp[2] = 2; for (int i = 3; i <= n; i++) { dp[i] = dp[i - 1] + dp[i - 2]; } return dp[n]; } int main() { int n; cout << "Enter the value of n: "; cin >> n; cout << "Number of ways to tile a 2x" << n << " board: " << tilingWays(n) << endl; // Print DP table for reference cout << "\nDP Table:\n"; cout << "n\t| Ways\n"; cout << "--------|------\n"; for (int i = 1; i <= n; i++) { cout << i << "\t| " << tilingWays(i) << "\n"; } return 0; }
Sample Output (n = 10)
Time Complexity: O(n) โ single pass through the array.
Space Complexity: O(n) for the DP array. Can be optimised to O(1) using two variables.
Viva Questions & Answers
V1. Why is the tiling problem similar to Fibonacci?
Both have the same recurrence: f(n) = f(n-1) + f(n-2). The tiling problem with base cases f(1)=1, f(2)=2 produces the Fibonacci sequence shifted by one position. This is because at each step, you have exactly two choices (vertical tile or horizontal pair), just like the two branches in Fibonacci.
V2. What happens if we also allow 1ร1 tiles?
If 1ร1 tiles are allowed on a 2รn board, the problem becomes more complex. You can no longer use a simple 1D DP. You'd need to track the state of each column (whether the bottom cell is filled or not), leading to a 2D state or bitmask DP approach.
V3. Can this problem be solved using matrix exponentiation?
Yes! Since f(n) = f(n-1) + f(n-2), we can write it as a matrix equation: [[f(n)],[f(n-1)]] = [[1,1],[1,0]]^(n-1) ร [[f(2)],[f(1)]]. Using matrix exponentiation, this gives O(log n) time complexity โ much faster than O(n) for very large n.
V4. What are the base cases and why?
f(1)=1: A 2ร1 board can only be filled with one vertical tile. f(2)=2: A 2ร2 board can be filled either with two vertical tiles or two horizontal tiles. These are the smallest boards that can be fully tiled.
V5. How would you extend this to a 3รn board?
A 3รn tiling is much harder. The recurrence is no longer simple. For a 3รn board with 2ร1 tiles: solutions exist only for even n. The recurrence involves multiple states tracking which cells in a column are filled. It requires profile DP (bitmask DP on column profiles). The simple f(n)=f(n-1)+f(n-2) doesn't apply.
Industry Spotlight โ A Day in the Life
๐ฉโ๐ป Sneha Gupta, 27 โ Algorithm Engineer at Flipkart, Bangalore
Background: B.Tech from NIT Warangal. Started competitive programming in 2nd year on CodeChef (5-star rated). Solved 500+ DP problems on LeetCode. Interned at Amazon for 2 months. Joined Flipkart through an off-campus referral from a CP community friend.
A Typical Day:
9:00 AM โ Morning standup with the pricing algorithms team. Review yesterday's price optimisation metrics.
10:00 AM โ Work on the dynamic pricing algorithm using DP to optimise prices across 50,000 product categories. The core is a knapsack variant that maximises revenue subject to margin constraints.
11:30 AM โ Code review for a colleague's warehouse allocation solution โ a variant of the bin-packing problem solved with DP.
1:00 PM โ Lunch at Flipkart's cafeteria. Discuss last weekend's CodeChef Long contest problem โ a tree DP problem that only 200 people solved.
2:00 PM โ Design a new DP-based recommendation engine that suggests product bundles (e.g., "phone + cover + screen guard" combos that maximise cart value).
4:00 PM โ Mentor 2 junior developers on DP thinking patterns. Today's topic: how to identify states and transitions.
5:30 PM โ Solve 2 LeetCode DP problems (maintains a daily streak of 400+ days). Today: "Burst Balloons" and "Palindrome Partitioning II."
| Detail | Info |
|---|---|
| Tools Used Daily | C++, Python, LeetCode, CodeChef, Git, VS Code, Internal ML platform |
| Entry Salary (2024) | โน12โ18 LPA + stocks |
| Mid-Level (3โ5 yrs) | โน25โ40 LPA |
| Senior (7+ yrs) | โน50โ80 LPA |
| Companies Hiring | Flipkart, Amazon, Google, Microsoft, Goldman Sachs, Tower Research Capital, DE Shaw, Uber, Razorpay |
Earn With It โ Freelance & Income Roadmap
๐ฐ Your Earning Path After This Chapter
Portfolio Piece: "Dynamic Programming Problem Solver" โ a GitHub repo with 20+ solved DP problems, each with explanation, DP table trace, and complexity analysis.
Beginner Gig Ideas:
โข DP tutoring for coding interview prep โ โน500โโน1,500/hour
โข Competitive programming coaching for juniors โ โน3,000โโน8,000/month per student
โข Creating DP problem sets for coaching institutes โ โน5,000โโน15,000/set
โข Content writing for coding education platforms โ โน2,000โโน5,000/article
| Platform | Best For | Typical Rate |
|---|---|---|
| Topmate | 1:1 coding mentorship sessions | โน500โโน2,000/session |
| Preplaced | Interview prep coaching | โน1,000โโน3,000/session |
| YouTube | DP tutorial video series | โน5,000โโน50,000/month (after growth) |
| Fiverr | Coding problem solutions & explanations | โน500โโน3,000/problem |
| Local Coaching | In-person tutoring at coaching centres | โน3,000โโน10,000/month |
โฑ๏ธ Time to First Earning: 1โ2 weeks (if you can solve 50+ DP problems confidently and create a Topmate profile)
Chapter Summary
๐ Key Takeaways โ Basic Dynamic Programming
- Dynamic Programming solves problems by storing solutions to overlapping subproblems, avoiding redundant computation.
- Two key properties: Overlapping Subproblems + Optimal Substructure. Both must hold for DP to apply.
- Two approaches: Memoization (top-down, recursive + cache) and Tabulation (bottom-up, iterative DP table).
- 5-Step Framework: Define state โ Write recurrence โ Base cases โ Iteration order โ Space optimisation.
- Classic problems covered: Fibonacci, Tiling (2รn), Climbing Stairs, Coin Change, House Robber, Min Cost Path.
- Tiling recurrence: f(n) = f(n-1) + f(n-2). Same structure as Fibonacci.
- Coin Change recurrence: dp[i] = min(dp[i-coin]+1) for all valid coins. Greedy doesn't always work.
- House Robber recurrence: dp[i] = max(dp[i-1], dp[i-2]+money[i]). Can't rob adjacent houses.
- Min Cost Path recurrence: dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1]).
- Time complexity: Most 1D DP is O(n). Grid DP is O(mรn). Coin change is O(amount ร |coins|).
- Space optimisation: Fibonacci/Stairs: O(n) โ O(1). Grid DP: O(mรn) โ O(n).
- DP patterns: Linear, Grid, Interval, Tree, Bitmask โ covering 90% of competitive programming DP problems.
Earning Checkpoint
| Skill Learned | Tool/Method | Portfolio Output | Can You Earn? |
|---|---|---|---|
| DP Concepts | Theory | โ | โ Yes โ discuss confidently in interviews |
| Fibonacci/Stairs DP | C++ | Solved problems on LeetCode | โ Yes โ basic interview ready |
| Coin Change | C++ | GitHub repo with solutions | โ Yes โ ready for SDE interviews |
| House Robber | C++ | Multiple variants solved | โ Yes โ medium-level interview ready |
| Min Cost Path (Grid DP) | C++ | Grid DP solutions portfolio | โ Yes โ covers grid DP pattern |
| DP Tutoring | Teaching | Session recordings/testimonials | โ Yes โ โน500โโน1,500/hour |
| Problem Set Creation | Documentation | Curated problem sets | โ Yes โ โน5,000โโน15,000/set |
โ Unit 4 complete. Ready for Unit 5: Advanced DP Techniques!
[QR: Link to EduArtha video tutorial โ Basic Dynamic Programming]