题目:入室盗贼2
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.
题意:
Note:这道题是题目House Robber(入室盗贼)的扩展。
抢完上一条街的房屋之后,小偷又给自己找了一个不太引人注意的新作案场所。这一次,所有的房屋围成一个环形。也就是说第一个房屋和最后一个房屋相邻。与此同时,这些房屋的安保系统与上一条街的相同。
给定一组非负整数代表每一件房屋的金钱数,求解在不惊动警察的情况下一晚上最多可以抢到的钱数。
思路一:
动态规划解。因为现在所有的房子排成了圆圈,如果抢了第一家就不能抢最后一家,因为首尾相连。所以第一家和最后一家只能抢两者之一,或者都不抢。处理过程中将分别将第一家跟最后一家去掉,各算一次能抢到的最多的钱,然后两次执行结果取最大值即为结果。
代码:C++版:
class Solution { public: int rob(vector<int>& nums) { if (nums.size() <= 1) return nums.empty() ? 0 : nums[0]; return max(rob(nums, 0, nums.size()-1), rob(nums, 1, nums.size())); //取去尾、去头分别取得的最大值即为结果 } int rob(vector<int> &nums, int left, int right) { if (right-left <= 1) return nums[left]; vector<int> dp(right, 0); dp[left] = nums[left]; dp[left+1] = max(nums[left], nums[left+1]); for (int i=left+2; i<right; ++i) { dp[i] = max(nums[i] + dp[i-2], dp[i-1]); //去第i家抢或者不抢获取的最大值 } return dp.back(); } };以另一种方案实现的rob函数功能,降低以上代码的空间复杂度。只是int rob(vector<int> &nums, int left, int right)函数实现方式不一样。
代码:C++版:0ms
class Solution { public: int rob(vector<int>& nums) { if (nums.size() <= 1) return nums.empty() ? 0 : nums[0]; return max(rob(nums, 0, nums.size()-1), rob(nums, 1, nums.size())); //取去尾、去头分别取得的最大值即为结果 } int rob(vector<int> &nums, int left, int right) { int take = 0, noTake = 0; for (int i=left; i<right; ++i) { int temp = take; take = noTake + nums[i]; noTake = max(temp, noTake); } return max(take, noTake); } };
思路二:
同样只是int rob(vector<int> &nums, int left, int right)函数实现方式不一样。本思路采用House Robber(入室盗贼)题目的思路二实现,采用奇偶的方式实现计算每次一次抢劫的方案的最大值。
代码:C++版:0ms
class Solution { public: int rob(vector<int>& nums) { if (nums.size() <= 1) return nums.empty() ? 0 : nums[0]; vector<int> v1 = nums, v2 = nums; v1.erase(v1.begin()); //v1去头 v2.pop_back(); //v2去尾 return max(rob_house(v1), rob_house(v2)); //取两者的最大值 } int rob_house(vector<int> &nums) { int even = 0, odd = 0; for (int i=0; i<nums.size(); ++i) { if (i%2 == 0) { even += nums[i]; even = max(even, odd); } else { odd += nums[i]; odd = max(even, odd); } } return max(even, odd); } };