You are given an integer array nums where nums[i] represents the amount of money the ith house has. The houses are arranged in a circle, i.e. the first house and the last house are neighbors.
You are planning to rob money from the houses, but you cannot rob two adjacent houses because the security system will automatically alert the police if two adjacent houses were both broken into.
Return the maximum amount of money you can rob without alerting the police.
1 ≤ nums.length ≤ 1000 ≤ nums[i] ≤ 200This is House Robber II, where houses are in a circle. Because of the circular setup, the first and last house cannot both be robbed.
To handle the circular constraint, we split the problem into two linear cases:
Each subproblem becomes the classic House Robber I, which we can solve and then return the maximum of the two results.
The recursive function explores skipping the current house, or robbing it and jumping two steps. A flag is used to ensure that if the first house is robbed, the last house is not allowed.
We use a DP table memo[index][flag]. The index represents the current house, and the flag denotes whether the first house was robbed.
Because houses are in a circle, we split the problem into two linear cases. Each case uses a bottom-up DP array just like House Robber I.
We run the Space Optimized House Robber I algorithm twice — once excluding the first house, and once excluding the last.
When there is only one house, the circular constraint does not apply since there is no adjacency conflict. If you split the problem into nums[1:] and nums[:-1] without handling this case, both subarrays become empty when n=1, and the function returns 0 instead of nums[0]. Always check if the array has only one element and return its value directly.
The key insight is that the first and last houses cannot both be robbed. A common mistake is to add complex flag logic throughout the recursion when a simpler approach exists: run the standard House Robber algorithm twice, once excluding the first house and once excluding the last house.
When splitting the array into nums[1:] (exclude first) and nums[:-1] (exclude last), be careful with slicing syntax. An off-by-one error here can lead to including both the first and last houses in one subproblem, or excluding more houses than intended.
Discussion
…