Given an array where each element is the money in a house along a street, maximise what you can rob without robbing two adjacent houses. e.g. [2,7,9,3,1] → 12 (rob houses 0, 2, 4).
Spotting the 'include-or-skip with an adjacency constraint' recurrence and collapsing it to O(1) space.
At each house you choose: rob it (its money + the best up to two houses back, since the neighbour is off-limits) or skip it (the best up to the previous house). So `dp[i] = max(dp[i-1], dp[i-2] + nums[i])`. Because each state looks back only two steps, you don't need the whole table — carry two rolling scalars `prev1` (best up to i-1) and `prev2` (best up to i-2) and update in place, giving O(1) space. This 'take-or-leave with a no-adjacent constraint' is a distinct DP signal from unbounded-choice problems like coin-change: here the constraint is positional adjacency. Variants layer on top: house-robber-II wraps the street into a circle (run the linear version twice — once excluding house 0, once excluding the last — and take the max), and the tree version (rob a binary tree) applies the same include/exclude at each node via DFS returning a pair.
Max/min over a sequence where picking i forbids i±1 → dp[i] = max(dp[i-1], dp[i-2] + value[i]).
Time O(n) · Space O(1)