House Robber II
Houses arranged in a circle — run linear House Robber on two ranges, exclude either head or tail.
3 min read
Problem#
Same as House Robber but houses are arranged in a circle — house 0 is adjacent to house n-1.
Examples#
[2,3,2]→3[1,2,3,1]→4
Constraints#
1 <= n <= 100.
Approach#
Run the linear DP twice: once on nums[0..n-2] (exclude last), once on nums[1..n-1] (exclude first). Return the max.
Solution#
class Solution {public: int rob(vector<int>& nums) { if (nums.size() == 1) return nums[0]; return max(robLinear(nums, 0, nums.size() - 2), robLinear(nums, 1, nums.size() - 1)); }private: int robLinear(vector<int>& nums, int lo, int hi) { int prev = 0, curr = 0; for (int i = lo; i <= hi; ++i) { int next = max(curr, prev + nums[i]); prev = curr; curr = next; } return curr; }};func rob(nums []int) int { n := len(nums) if n == 1 { return nums[0] } maxI := func(a, b int) int { if a > b { return a } return b } robLinear := func(lo, hi int) int { prev, curr := 0, 0 for i := lo; i <= hi; i++ { next := maxI(curr, prev+nums[i]) prev = curr curr = next } return curr } return maxI(robLinear(0, n-2), robLinear(1, n-1))}from typing import List
class Solution: def rob(self, nums: List[int]) -> int: n = len(nums) if n == 1: return nums[0]
def rob_linear(lo: int, hi: int) -> int: prev = curr = 0 for i in range(lo, hi + 1): prev, curr = curr, max(curr, prev + nums[i]) return curr
return max(rob_linear(0, n - 2), rob_linear(1, n - 1))function rob(nums) { const n = nums.length; if (n === 1) return nums[0]; function robLinear(lo, hi) { let prev = 0, curr = 0; for (let i = lo; i <= hi; i++) { const next = Math.max(curr, prev + nums[i]); prev = curr; curr = next; } return curr; } return Math.max(robLinear(0, n - 2), robLinear(1, n - 1));}class Solution { public int rob(int[] nums) { int n = nums.length; if (n == 1) return nums[0]; return Math.max(robLinear(nums, 0, n - 2), robLinear(nums, 1, n - 1)); }
private int robLinear(int[] nums, int lo, int hi) { int prev = 0, curr = 0; for (int i = lo; i <= hi; i++) { int next = Math.max(curr, prev + nums[i]); prev = curr; curr = next; } return curr; }}function rob(nums: number[]): number { const n = nums.length; if (n === 1) return nums[0]; const robLinear = (lo: number, hi: number): number => { let prev = 0, curr = 0; for (let i = lo; i <= hi; i++) { const next = Math.max(curr, prev + nums[i]); prev = curr; curr = next; } return curr; }; return Math.max(robLinear(0, n - 2), robLinear(1, n - 1));}Editorial#
The circular constraint reduces to two non-circular cases: either the first house is robbed (then the last can’t be) or the first isn’t (the last is free game). Linear House Robber over each window covers both.
Complexity#
- Time: O(n).
- Space: O(1).
Concept revision#
Related#