House Robber II
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 100 - ◆
0 ≤ nums[i] ≤ 400 - ◆
The houses are arranged in a circle: the first and last houses are adjacent to each other.
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Recursive Without Memoization
BruteBecause the houses form a circle, the first and last houses are adjacent, so they can never both be robbed. That means a valid plan either robs from a range that stops before the last house, or one that starts after the first house — one of those two linear ranges is guaranteed to contain the true best plan (a lone house is handled separately since it has no meaningful "circle" to break). Each of those two ranges is just the ordinary House Robber recursion, generalized to take a starting index and an ending index instead of always running to the end of the array: at every house in range, either skip it and move to the next, or rob it and jump two ahead. The larger result from the two ranges is the overall answer.
O(2^n)O(n)1class Solution {
2 private int[] nums;
3
4 public int houseRobberII(int[] nums) {
5 this.nums = nums;
6 int n = nums.length;
7 if (n == 1) return nums[0];
8 return Math.max(solve(0, n - 2), solve(1, n - 1));
9 }
10
11 private int solve(int i, int end) {
12 if (i > end) return 0;
13 int skip = solve(i + 1, end);
14 int take = nums[i] + solve(i + 2, end);
15 return Math.max(skip, take);
16 }
17}Optimal — Bottom-Up 1D DP
OptimalThe same two-range idea applies to the constant-space sliding version of House Robber: run the prev2/prev1 sweep once over the range that excludes the last house, run it again over the range that excludes the first house, and return whichever total is larger. Neither sweep ever considers robbing both the first and last house together, so the circular constraint is respected automatically, and each sweep itself still only needs O(1) extra space.
O(n)O(1)1class Solution {
2 public int houseRobberII(int[] nums) {
3 int n = nums.length;
4 if (n == 1) return nums[0];
5 return Math.max(robRange(nums, 0, n - 2), robRange(nums, 1, n - 1));
6 }
7
8 private int robRange(int[] nums, int start, int end) {
9 int prev2 = 0, prev1 = 0;
10 for (int i = start; i <= end; i++) {
11 int cur = Math.max(prev1, prev2 + nums[i]);
12 prev2 = prev1;
13 prev1 = cur;
14 }
15 return prev1;
16 }
17}