Recognize the Pattern
- Different decision paths reach the same remaining subproblem.
- The optimum or count can be composed from smaller states without losing a relevant condition.
- Constraints make the state space affordable; count distinct states before allocating a table.
Core Invariant
Before processing a house, oneBack is the optimum before it and twoBack is the optimum before its neighbor. Compute the new total before shifting either value.
Important Boundary
Taking a house must use the prefix before its neighbor. Two compressed totals return the optimum but lose the selected-house history.
Write a sentence for every state
House Robber allows selecting nothing: best[0] = 0 and best[1] = nums[0] for a nonempty input. That does not mean every DP starts at zero. Minimum-coin DP initializes unreachable positive amounts to Infinity; only amount zero needs zero coins.
| Problem | State meaning | Composition |
|---|---|---|
| House Robber | Best value in the first i houses. | Skip the last, or take it plus the prefix before its neighbor. |
| Coin Change | Fewest coins making exactly amount a. | Try a final coin and add one to the remaining amount. |
| Word Break | Whether prefix ending at i can be segmented. | Find an earlier reachable boundary and a dictionary suffix. |
Derive skip-or-take choices before compressing storage
Let best[i] be the maximum total from the first i houses. Skip house i-1 to keep best[i-1], or take it and add nums[i-1] to best[i-2]. Thus best[i] = max(best[i-1], best[i-2] + nums[i-1]). Taking a house excludes its immediate neighbor, not every earlier house.
Before processing index i, oneBack stores best[i] and twoBack stores best[max(0, i-1)]. Compute current before replacing either value. After the update, oneBack stores best[i+1]. The loop also handles an empty array by returning zero.
Template Assumptions
- A linear array of nonnegative integer house values; the empty array returns zero.
- Adjacent houses cannot both be selected. Returns only the maximum total, without mutating the input or reconstructing the selected houses.
JavaScript Template
- Updating twoBack before computing current would read the wrong prefix and can allow adjacent houses. Save the new answer first, then shift the two prior answers.
- Two stored totals are enough to return the optimum, but do not identify the chosen houses. Keep the prefix table and backtrack through skip-or-take decisions when reconstruction is required; ties can have several valid optimal selections.
Trace the two choices for each house
For [2,7,9,3,1], the full prefix table is [0,2,7,11,11,12]. Taking indices 0, 2, and 4 yields 12. A greedy rule that always takes the largest next house misses that 2 + 9 beats 7. Choosing one index parity globally is also insufficient: [2,1,1,2] is best solved by taking the two endpoints for 4.
| House index / value | Skip | Take | Best prefix total |
|---|---|---|---|
| 0 / 2 | 0 | 0 + 2 | 2 |
| 1 / 7 | 2 | 0 + 7 | 7 |
| 2 / 9 | 7 | 2 + 9 | 11 |
| 3 / 3 | 11 | 7 + 3 | 11 |
| 4 / 1 | 11 | 11 + 1 | 12 |
Step-by-Step: House Robber: skip or take each house
- House index
- none
- Skip
- 0
- Take
- 0
- Computed prefix totals
- [0]
- Best total so far
- 0
- twoBack after update
- 0
- oneBack after update
- 0
Start with the empty prefix
Cell i represents the best total from the first i houses. Only best[0] is computed: zero houses yield zero. The input is [2,7,9,3,1].
Choose dependency order and scope
- Memoization discovers needed states recursively; tabulation orders dependencies explicitly. Both still require the same complete state key.
- House Robber II splits the cycle into two linear cases: exclude the first or exclude the last. The one-house case must not accidentally become two empty ranges.
- Tree DP has its own guide: conditional subtree return values are not a one-dimensional prefix recurrence.
- Some DP problems admit stronger algorithms. LIS has an O(N squared) predecessor DP and an O(N log N) tails method; do not assume a table is always the final optimization.
Count states times transition work
- House Robber costs O(N) time: each prefix has two constant-time choices. The full table uses O(N) auxiliary space; the displayed code uses O(1).
- Other DP problems can cost more per state. For Word Break, trying several earlier split points and checking their words adds work beyond counting prefix positions.
- Memoization recursion adds call-stack storage and may hit JavaScript depth limits. Output reconstruction, slicing, and dictionary checks add costs beyond the nominal DP state count.
Mistakes and Counterexamples
Initialize every minimization state to zero.
Counterexample: Making amount 3 from only coin 2 is impossible, but a zero-filled table can suggest it needs no coins.
Correction: Represent unreachable states explicitly and give zero only to the valid empty base case.
Memoize by an incomplete subproblem key.
Counterexample: In a recursive House Robber solution, whether the previous house was taken changes the allowed choices at the same index. Caching only by index is incorrect if that flag is part of the recursive contract.
Correction: Include every dimension that changes the remaining choices, or define robFrom(i) to always start with house i available and advance by one when skipping or by two when taking.
Last-Minute Recap
- State meaning comes before storage.
- Base cases distinguish empty from unreachable.
- Transitions must read the intended logical states.
- Count states, transitions, stack, and reconstruction separately.
Explain It in an Interview
- Give a complete sentence for the DP state and every dimension in its key.
- Why does taking a house read the prefix two positions back, and why must current be computed before shifting the stored totals?
- What information is lost when compressing the table, and how would you reconstruct a choice?
Ready to Apply This Pattern?
Before coding, explain why this pattern fits and what must stay true at each step. Start with an easier problem, then test that reasoning on a harder variation.
Ordered from Easy to Hard. Premium access requirements still apply.
- 1.Climbing Stairs - Ways to ReachDefine the count for each prefix and justify the zero-step base state.Easy
- 2.Best Time to Buy and Sell StockTrack the best prior purchase price and preserve the requirement that buying precedes selling.Easy
- 3.House RobberSeparate skipping from taking a house and retain the correct two prefix answers.Medium
- 4.House Robber IIBreak the circular adjacency constraint into two valid linear cases.Medium
- 5.Coin Change - Minimum CoinsDistinguish exact-amount reachability from zero-cost initialization.Medium
- 6.Word BreakDefine reachable prefix boundaries and include substring or matching costs.Medium
- 7.Longest Increasing SubsequenceCompare predecessor DP with the minimum-tail summary and binary-search optimization.Medium
- 8.Partition Equal Subset SumReduce equal partition to subset-sum reachability and update capacities backward to prevent reuse.Medium
- 9.0/1 KnapsackDefine capacity states and iterate backward when compressing a table for single-use items.Medium
- 10.Cheapest Flights Within K StopsRelax from the previous edge-budget layer so one iteration cannot consume several flights.Medium
- 11.Maximum Subarray - Best Period AnalysisSeparate the best subarray ending here from the best answer across all endpoints.Medium
- 12.Decode WaysCount valid prefix decodings and reject invalid zero and two-digit transitions.Medium
- 13.Longest Palindromic SubstringDefine interval validity from inner substrings and process lengths in dependency order.Medium