[LeetCode] House Robber II 打家劫舍之二
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
类似题目:
Non-negative Integers without Consecutive Ones
参考资料:
https://leetcode.com/problems/house-robber-ii/
https://leetcode.com/problems/house-robber-ii/discuss/59929/Java-clean-short-solution-DP
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] House Robber II 打家劫舍之二的更多相关文章
- [LintCode] House Robber II 打家劫舍之二
After robbing those houses on that street, the thief has found himself a new place for his thievery ...
- [LeetCode] 213. House Robber II 打家劫舍之二
You are a professional robber planning to rob houses along a street. Each house has a certain amount ...
- [LeetCode]House Robber II (二次dp)
213. House Robber II Total Accepted: 24216 Total Submissions: 80632 Difficulty: Medium Note: Thi ...
- [LeetCode] House Robber III 打家劫舍之三
The thief has found himself a new place for his thievery again. There is only one entrance to this a ...
- [LeetCode] 213. House Robber II 打家劫舍 II
Note: This is an extension of House Robber. After robbing those houses on that street, the thief has ...
- [LeetCode] 47. Permutations II 全排列之二
Given a collection of numbers that might contain duplicates, return all possible unique permutations ...
- [LeetCode] Meeting Rooms II 会议室之二
Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si ...
- [LeetCode] The Maze II 迷宫之二
There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...
- 213 House Robber II 打家劫舍 II
注意事项: 这是 打家劫舍 的延伸.在上次盗窃完一条街道之后,窃贼又转到了一个新的地方,这样他就不会引起太多注意.这一次,这个地方的所有房屋都围成一圈.这意味着第一个房子是最后一个是紧挨着的.同时,这 ...
随机推荐
- 解决新版Android studio导入微信支付和支付宝官方Demo的问题
最近项目要用到支付宝支付和微信支付,本想使用第三方支付框架ping++或者BeeCloud的,但是由于他们的收费问题,让我望而却步,而且公司给了相应的公钥.私钥和APPID等,所以就用下开放平台的呗. ...
- 你真的会玩SQL吗?实用函数方法汇总
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- WCF备忘录一:服务端实例的生命周期
示例代码下载地址:WCFDemo1Day 概述 客户端向WCF服务发出请求后,服务端会实例化一个Service对象(实现了契约接口的对象)用来处理请求,实例化Service对象以及维护其生命周期的方式 ...
- helios架构详解(一)服务器端架构
看了“菜鸟耕地”的”.NET开源高性能Socket通信中间件Helios介绍及演示“,觉得这个东西不错.但是由于没有网络编程知识,所以高性能部分我就讲不出来了,主要是想根据开源代码跟大家分享下Heli ...
- 初识ASP.NET MVC
我们首先从创建ASP.NET MVC项目开始.打开Visual Studio,在文件菜单中选择新建-> 项目,然后在模板中选择Web,接着选择ASP.Net Web应用程序,更改项目名称,点击确 ...
- C#开发微信门户及应用(9)-微信门户菜单管理及提交到微信服务器
微信公众号(包括服务号和订阅号)都可以对菜单进行自定义设置,我们为了方便管理,一般先把菜单数据在本地管理维护,需要更新的时候,把它们更新到微信服务器上就可以了.本文基于这个方式,介绍我的微信门户平台管 ...
- spring mvc 和spring security配置 web.xml设置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmln ...
- String类
字符串的功能 A:判断功能 boolean equals(Object obj)//比较对象 boolean eq ...
- 关getClass().getClassLoader()
InputStream is = getClass().getClassLoader().getResourceAsStream("helloworld.properties&q ...
- HotApp小程序统计,第一个专业的微信第三方小程序统计工具
1.什么是HotApp小程序统计 HotApp小程序统计是第一个微信第三方小程序统计工具,就像做android 和 ios开发的人知道友盟统计一样,小程序也需要有个统计工具. 通过这个工具,可以知道小 ...