Baozi Training Leetcode solution 213. House Robber II
Problem Statement
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
Example 1:
Input: [2,3,2] Output: 3 Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), because they are adjacent houses.
Example 2:
Input: [1,2,3,1] Output: 4 Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). Total amount you can rob = 1 + 3 = 4.
Problem link
Video Tutorial
You can find the detailed video tutorial here
Thought Process
This is very similar to House Robber I problem
where the only difference is the houses now form a circle (French fancy
way calls it cul-de-sac). It's same DP algorithm except now we need to
consider two cases: whether we rob the first house or not. If we rob the
first house, we should not rob the last house. If we do not rob the
first house, we can rob the last house. We can even reuse the rob()
function in House Robber I problem
Solutions
Use DP
1 public int rob(int[] nums) { 2 if (nums == null || nums.length == 0) { 3 return 0; 4 } 5 if (nums.length == 1) { 6 return nums[0]; 7 } 8 9 // rob first house, so need to remove the last house 10 int[] rob_first_nums = new int[nums.length - 1]; 11 for (int i = 0; i < rob_first_nums.length; i++) { 12 rob_first_nums[i] = nums[i]; 13 } 14 15 // do not rob first house, start from the 2nd and rob to the end of the house 16 int[] rob_no_first_nums = new int[nums.length - 1]; 17 for (int i = 1; i < nums.length; i++) { 18 rob_no_first_nums[i - 1] = nums[i]; 19 } 20 21 int rob_first_max = this.robFlatRow(rob_first_nums); 22 int rob_no_first_max = this.robFlatRow(rob_no_first_nums); 23 24 return Math.max(rob_first_max, rob_no_first_max); 25 } 26 27 public int robFlatRow(int[] num) { 28 if (num == null || num.length == 0) { 29 return 0; 30 } 31 32 int n = num.length; 33 int[] lookup = new int[n + 1]; // DP array size normally larger than 1 34 lookup[0] = 0; 35 lookup[1] = num[0]; 36 37 for (int i = 2; i <= n; i++) { 38 lookup[i] = Math.max(lookup[i - 1], lookup[i - 2] + num[i - 1]); 39 } 40 41 return lookup[n]; 42 }
Time Complexity: O(N), N is the array size
Space Complexity: O(N) since we use extra arrays