DP - 1D · Medium
LeetCode 198: House Robber — solution
1D DP with a take-or-skip choice at every house: the best total up to house i is the larger of skipping it or robbing it plus the best up to i - 2. O(n) time and O(1) space.
Problem in plain words
Houses stand in a row and each holds some money. You can rob any set of houses as long as no two chosen houses are next to each other (adjacent robberies trigger an alarm). Return the largest total you can collect.
For example, with [5, 1, 1, 5] the best plan robs the first and last houses for 10; robbing the two middle ones is not allowed.
Intuition
At each house you face one decision. Skip it, and your best total is whatever you had after the previous house. Rob it, and you must have skipped the previous house, so you add its money to the best total from two houses back. Taking the larger option at every house gives the optimum, because the best answer for a prefix never depends on anything further right. Like the bottom-up Fibonacci DP lesson, only two earlier values are ever needed.
Approach
- State:
best[i]is the most money from houses0..i. - Recurrence:
best[i] = max(best[i - 1], best[i - 2] + nums[i]). - Base cases: treat
best[-2] = best[-1] = 0, so the first house givesbest[0] = nums[0]. - Order: left to right, storing the previous two values as
prev2andprev1. The answer isprev1at the end.
Dry run
Input: nums = [3, 1, 4, 9, 2].
| House | Money | Skip (prev1) | Rob (prev2 + money) | best |
|---|---|---|---|---|
| 0 | 3 | 0 | 0 + 3 = 3 | 3 |
| 1 | 1 | 3 | 0 + 1 = 1 | 3 |
| 2 | 4 | 3 | 3 + 4 = 7 | 7 |
| 3 | 9 | 7 | 3 + 9 = 12 | 12 |
| 4 | 2 | 12 | 7 + 2 = 9 | 12 |
The answer is 12, from robbing houses 0 and 3.
Java solution
class Solution {
public int rob(int[] nums) {
int prev2 = 0, prev1 = 0; // best up to i-2, best up to i-1
for (int money : nums) {
int current = Math.max(prev1, prev2 + money);
prev2 = prev1;
prev1 = current;
}
return prev1;
}
}Python solution
class Solution:
def rob(self, nums: List[int]) -> int:
prev2, prev1 = 0, 0 # best up to i-2, best up to i-1
for money in nums:
prev2, prev1 = prev1, max(prev1, prev2 + money)
return prev1Complexity
| Measure | Cost | Why |
|---|---|---|
| Time | O(n) | One max per house. |
| Space | O(1) | Two rolling variables replace the dp array. |
Edge cases and common mistakes
- One house: the loop runs once and returns
nums[0]. - Robbing every other house greedily: picking all even or all odd indices fails on inputs like
[2, 1, 1, 9], where the best is 2 + 9 = 11 (indices 0 and 3). - Zero-money houses: values can be 0; the max handles them without special cases.
- Variable update order: compute the new value before shifting
prev2 = prev1, or you lose the value from two houses back.
›What changes if the houses are in a circle?
The first and last houses become neighbours. Run this same function twice, once without the last house and once without the first, and take the larger result (that is LeetCode 213).
