Skip to content

Commit 63e90d4

Browse files
authored
Revise dynamic programming considerations and pitfalls
1 parent d561050 commit 63e90d4

File tree

1 file changed

+15
-12
lines changed

1 file changed

+15
-12
lines changed

notes/dynamic_programming.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -288,30 +288,33 @@ We build a two-dimensional table $L[0..m][0..n]$ using the above recurrence.
288288

289289
**Time Complexity**: $O(mn)$
290290

291-
### Practical Considerations in Dynamic Programming
291+
### Practical Considerations
292292

293293
#### Identifying DP Problems
294294

295-
Not all problems are amenable to dynamic programming. To determine if DP is appropriate:
296-
297-
- Can the problem's optimal solution be constructed from optimal solutions to its subproblems?
298-
- Are the same subproblems being solved multiple times?
295+
* If the problem asks for the number of *ways* to do something, DP usually works because smaller counts combine into larger ones; without it, counting paths in a grid would require enumerating every route.
296+
* If the task is to find the *minimum* or *maximum* value under constraints, DP is useful because it compares partial solutions; without it, knapsack would require checking every subset of items.
297+
* If the same *inputs* appear again during recursion, DP saves time by storing answers; without it, Fibonacci numbers would be recomputed many times.
298+
* If the solution depends on both the *current step* and *remaining resources* (time, weight, money, length), DP fits naturally; without it, scheduling tasks within a time limit would require brute force.
299+
* If the problem works with *prefixes, substrings, or subsequences*, DP is often a match because these can be built step by step; without it, longest common subsequence would need exponential checking.
300+
* If choices at each step must be explored and combined carefully, DP provides structure; without it, coin change with mixed denominations cannot guarantee the fewest coins.
301+
* If the state space can be stored in a *table or array*, DP is feasible; without this, problems with infinitely many possibilities (like arbitrary real numbers) cannot be handled.
299302

300303
#### State Design and Transition
301304

302-
- Choose variables that capture the essence of subproblems.
303-
- Clearly define how to move from one state to another.
305+
* A well-chosen *state* defines what each subproblem represents, while a poorly chosen one leaves the formulation incomplete; for example, `dp[i][w]` in the knapsack problem captures value using `i` items and capacity `w`.
306+
* A correct *transition* connects states consistently, while skipping this leads to undefined progress; in knapsack, the choice to include or exclude an item gives the formula for moving between states.
304307

305308
#### Complexity Optimization
306309

307-
- Reduce the storage requirements by identifying and storing only necessary states.
308-
- Prune unnecessary computations, possibly using techniques like memoization with pruning.
310+
* Reducing *memory usage* by discarding unnecessary states makes solutions efficient, while failing to do so can waste resources; for example, knapsack space can shrink from `O(nW)` to `O(W)` with a one-dimensional array.
311+
* Using *pruning* to skip impossible paths speeds up computation, while omitting it allows redundant work; in recursive search with memoization, branches exceeding a current best value can be safely ignored.
309312

310313
#### Common Pitfalls
311314

312-
- Leads to missing subproblems or incorrect dependencies.
313-
- Can cause incorrect results or infinite recursion.
314-
- Failing to handle special inputs can result in errors.
315+
* Missing *base cases* causes results to fail, while including them ensures correct foundations; in grid path counting, setting `dp[0][0] = 1` allows all later counts to build properly.
316+
* Updating *dependencies* in the wrong order leads to invalid reuse, while correct order avoids errors; in knapsack with a 1D array, iterating weights backward prevents an item from being counted twice.
317+
* Ignoring *edge inputs* results in crashes or incorrect answers, while handling them ensures robustness; for example, knapsack with zero capacity must return a value of zero instead of failing.
315318

316319
### List of Problems
317320

0 commit comments

Comments
 (0)