LeetCode 213. House Robber II
题目描述
Note: This is an extension of House Robber.
After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.
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.
在House Robber的基础上,这个题目增加的一个限制就是所有的房屋构成了一个环,在这种情况下保证任不偷盗任意两间相邻的房子。
解题思路
首先:如果房屋不构成一个圈,我们的解法有如下几种可能
- 头部和尾部的房屋都被抢劫
- 头部房屋被抢劫,尾部房屋没有被抢劫
- 头部房屋没有被抢劫,尾部的房屋被抢劫
- 头部和尾部的房屋都没有被抢劫
如果房屋形成一个环,我们的最优解就只能选择后面的三种情况,第二种情况我们要保证最后一个房屋不能被抢劫,第三种情况要保证第一个房屋不能被抢劫,第四种情况已经包含在前两种情况中了。其实就是在环的连接处保证其中一个不被偷的情况下,求出从剩下的房屋中最多能盗取的金钱数目。
因此在House Robber的基础上我们只要保证结果只能为上面第二和第三种情况即可。
代码如下:
class Solution { public int rob(int[] nums) { if(nums == null || nums.length == 0) return 0; if(nums.length == 1) return nums[0]; if(nums.length == 2) return Math.max(nums[0], nums[1]); // 保证第一家安全和保证最后一家安全中的最大值 return Math.max(robMax(nums, 1, nums.length - 1), robMax(nums, 0, nums.length - 2)); } public int robMax(int[] nums, int begin, int end){ int[] dp = new int[end - begin + 1]; dp[0] = nums[begin]; dp[1] = Math.max(nums[begin], nums[begin+1]); for(int j=2; j<dp.length ; j++){ dp[j] = Math.max(dp[j-1], dp[j-2]+nums[j+begin]); } return dp[dp.length - 1]; } }
上面代码的空间复杂度为O(n),我们发现其实不必把已经计算过的所有信息保存下来,只要保存后两个记录即可,优化后的空间复杂度为O(1),代码如下:
class Solution { public int rob(int[] nums) { if (nums.length == 1) return nums[0]; return Math.max(rob(nums, 1, nums.length - 1), rob(nums, 0, nums.length - 2)); } private int rob(int[] nums, int lo, int hi) { int include = 0, exclude = 0; for (int j = lo; j <= hi; j++) { int i = include, e = exclude; include = e + nums[j]; exclude = Math.max(e, i); } return Math.max(include, exclude); } }

浙公网安备 33010602011771号