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.

Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.

这道题是之前那道 House Robber 的拓展,现在房子排成了一个圆圈,则如果抢了第一家,就不能抢最后一家,因为首尾相连了,所以第一家和最后一家只能抢其中的一家,或者都不抢,那这里变通一下,如果把第一家和最后一家分别去掉,各算一遍能抢的最大值,然后比较两个值取其中较大的一个即为所求。那只需参考之前的 House Robber 中的解题方法,然后调用两边取较大值,代码如下:

解法一:

class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() <= ) return nums.empty() ? : nums[];
return max(rob(nums, , nums.size() - ), rob(nums, , nums.size()));
}
int rob(vector<int> &nums, int left, int right) {
if (right - left <= ) return nums[left];
vector<int> dp(right, );
dp[left] = nums[left];
dp[left + ] = max(nums[left], nums[left + ]);
for (int i = left + ; i < right; ++i) {
dp[i] = max(nums[i] + dp[i - ], dp[i - ]);
}
return dp.back();
}
};

当然,我们也可以使用两个变量来代替整个 DP 数组,讲解与之前的帖子 House Robber 相同,分别维护两个变量 robEven 和 robOdd,顾名思义,robEven 就是要抢偶数位置的房子,robOdd 就是要抢奇数位置的房子。所以在遍历房子数组时,如果是偶数位置,那么 robEven 就要加上当前数字,然后和 robOdd 比较,取较大的来更新 robEven。这里就看出来了,robEven 组成的值并不是只由偶数位置的数字,只是当前要抢偶数位置而已。同理,当奇数位置时,robOdd 加上当前数字和 robEven 比较,取较大值来更新 robOdd,这种按奇偶分别来更新的方法,可以保证组成最大和的数字不相邻,最后别忘了在 robEven 和 robOdd 种取较大值返回,代码如下:

解法二:

class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() <= ) return nums.empty() ? : nums[];
return max(rob(nums, , nums.size() - ), rob(nums, , nums.size()));
}
int rob(vector<int> &nums, int left, int right) {
int robEven = , robOdd = ;
for (int i = left; i < right; ++i) {
if (i % == ) {
robEven = max(robEven + nums[i], robOdd);
} else {
robOdd = max(robEven, robOdd + nums[i]);
}
}
return max(robEven, robOdd);
}
};

另一种更为简洁的写法,讲解与之前的帖子 House Robber 相同,我们使用两个变量 rob 和 notRob,其中 rob 表示抢当前的房子,notRob 表示不抢当前的房子,那么在遍历的过程中,先用两个变量 preRob 和 preNotRob 来分别记录更新之前的值,由于 rob 是要抢当前的房子,那么前一个房子一定不能抢,所以使用 preNotRob 加上当前的数字赋给 rob,然后 notRob 表示不能抢当前的房子,那么之前的房子就可以抢也可以不抢,所以将 preRob 和 preNotRob 中的较大值赋给 notRob,参见代码如下:

解法三:

class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() <= ) return nums.empty() ? : nums[];
return max(rob(nums, , nums.size() - ), rob(nums, , nums.size()));
}
int rob(vector<int> &nums, int left, int right) {
int rob = , notRob = ;
for (int i = left; i < right; ++i) {
int preRob = rob, preNotRob = notRob;
rob = preNotRob + nums[i];
notRob = max(preRob, preNotRob);
}
return max(rob, notRob);
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/213

类似题目:

House Robber

House Robber III

Paint House

Paint Fence

Non-negative Integers without Consecutive Ones

Coin Path

参考资料:

https://leetcode.com/problems/house-robber-ii/

https://leetcode.com/problems/house-robber-ii/discuss/59929/Java-clean-short-solution-DP

https://leetcode.com/problems/house-robber-ii/discuss/59934/Simple-AC-solution-in-Java-in-O(n)-with-explanation

LeetCode All in One 题目讲解汇总(持续更新中...)

最新文章

  1. OAF_开发系列23_实现OAF数据格式CSS和CSS库(案例)
  2. linux bash中too many arguments问题的解决方法
  3. Python地址簿
  4. mysql常用函数整理
  5. linux配置IP地址
  6. (转)深入浅出 iOS 之生命周期
  7. [ASP.NET]动态绑定树控件:
  8. [转]sql利用游标循环,遍历表循环结果集
  9. [HIHO1039]字符消除(字符串,枚举,模拟)
  10. C#double保留两位小数
  11. [转载]请教各位高手光盘版或者U盘版的BT保存配置的问题
  12. Elasticsearch安装使用
  13. 利用Eclipse中的Maven构建Web项目(一)
  14. MySql思维导图
  15. Rsync使用方法
  16. XFS文件系统的备份和恢复
  17. PHP多进程的实际处理
  18. iOS开发简记(5):设备唯一标识与全局变量
  19. Springboot项目修改html后不需要重启---springboot项目的热部署
  20. HTML+CSS+JS 传智 详细笔记

热门文章

  1. OAuth2.0授权码模式
  2. 用Java开发的【智能语音开发板MEGA ESP32AI】
  3. 什么是JavaBean?
  4. Spring Cloud Hystrix Dashboard熔断器-Turbine集群监控(六)
  5. JVM的监控工具之jvisual
  6. 先排序然后union all失效,mysql数据库多个表union all查询并排序的结果为什么错误
  7. MongoDB常用数据库命令第三集
  8. Python从零开始——函数
  9. ES6的相关语法
  10. flask 案例项目基本框架的搭建