[LeetCode] House Robber 打家劫舍
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that 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: [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.
Example 2:
Input: [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.
Credits:
Special thanks to @ifanchu for adding this problem and creating all test cases. Also thanks to @ts for adding additional test cases.
这道题的本质相当于在一列数组中取出一个或多个不相邻数,使其和最大。那么对于这类求极值的问题首先考虑动态规划 Dynamic Programming 来解,维护一个一位数组 dp,其中 dp[i] 表示 [0, i] 区间可以抢夺的最大值,对当前i来说,有抢和不抢两种互斥的选择,不抢即为 dp[i-1](等价于去掉 nums[i] 只抢 [0, i-1] 区间最大值),抢即为 dp[i-2] + nums[i](等价于去掉 nums[i-1])。再举一个简单的例子来说明一下吧,比如说 nums为{3, 2, 1, 5},那么来看 dp 数组应该是什么样的,首先 dp[0]=3 没啥疑问,再看 dp[1] 是多少呢,由于3比2大,所以抢第一个房子的3,当前房子的2不抢,则dp[1]=3,那么再来看 dp[2],由于不能抢相邻的,所以可以用再前面的一个的 dp 值加上当前的房间值,和当前房间的前面一个 dp 值比较,取较大值当做当前 dp 值,这样就可以得到状态转移方程 dp[i] = max(num[i] + dp[i - 2], dp[i - 1]), 且需要初始化 dp[0] 和 dp[1],其中 dp[0] 即为 num[0],dp[1] 此时应该为 max(num[0], num[1]),代码如下:
解法一:
class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() <= ) return nums.empty() ? : nums[];
vector<int> dp = {nums[], max(nums[], nums[])};
for (int i = ; i < nums.size(); ++i) {
dp.push_back(max(nums[i] + dp[i - ], dp[i - ]));
}
return dp.back();
}
};
还有一种解法,核心思想还是用 DP,分别维护两个变量 robEven 和 robOdd,顾名思义,robEven 就是要抢偶数位置的房子,robOdd 就是要抢奇数位置的房子。所以在遍历房子数组时,如果是偶数位置,那么 robEven 就要加上当前数字,然后和 robOdd 比较,取较大的来更新 robEven。这里就看出来了,robEven 组成的值并不是只由偶数位置的数字,只是当前要抢偶数位置而已。同理,当奇数位置时,robOdd 加上当前数字和 robEven 比较,取较大值来更新 robOdd,这种按奇偶分别来更新的方法,可以保证组成最大和的数字不相邻,最后别忘了在 robEven 和 robOdd 种取较大值返回,代码如下:
解法二:
class Solution {
public:
int rob(vector<int>& nums) {
int robEven = , robOdd = , n = nums.size();
for (int i = ; i < n; ++i) {
if (i % == ) {
robEven = max(robEven + nums[i], robOdd);
} else {
robOdd = max(robEven, robOdd + nums[i]);
}
}
return max(robEven, robOdd);
}
};
上述方法还可以进一步简洁,我们使用两个变量 rob 和 notRob,其中 rob 表示抢当前的房子,notRob 表示不抢当前的房子,那么在遍历的过程中,先用两个变量 preRob 和 preNotRob 来分别记录更新之前的值,由于 rob 是要抢当前的房子,那么前一个房子一定不能抢,所以使用 preNotRob 加上当前的数字赋给 rob,然后 notRob 表示不能抢当前的房子,那么之前的房子就可以抢也可以不抢,所以将 preRob 和 preNotRob 中的较大值赋给 notRob,参见代码如下:
解法三:
class Solution {
public:
int rob(vector<int>& nums) {
int rob = , notRob = , n = nums.size();
for (int i = ; i < n; ++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/198
类似题目:
Non-negative Integers without Consecutive Ones
参考资料:
https://leetcode.com/problems/house-robber/description/
https://leetcode.com/problems/house-robber/discuss/55681/java-on-solution-space-o1
https://leetcode.com/problems/house-robber/discuss/55693/c-1ms-o1space-very-simple-solution
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] House Robber 打家劫舍的更多相关文章
- [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] House Robber II 打家劫舍之二
Note: This is an extension of House Robber. After robbing those houses on that street, the thief has ...
- [LeetCode] 198. House Robber 打家劫舍
You are a professional robber planning to rob houses along a street. Each house has a certain amount ...
- 【LeetCode】198. House Robber 打家劫舍 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 递归 + 记忆化 动态规划 优化动态规划空间 ...
- LeetCode House Robber III
原题链接在这里:https://leetcode.com/problems/house-robber-iii/ 题目: The thief has found himself a new place ...
- [LintCode] House Robber 打家劫舍
You are a professional robber planning to rob houses along a street. Each house has a certain amount ...
- LeetCode House Robber
原题链接在这里:https://leetcode.com/problems/house-robber/ 题目: You are a professional robber planning to ro ...
- Leetcode House Robber II
本题和House Robber差不多,分成两种情况来解决.第一家是不是偷了,如果偷了,那么最后一家肯定不能偷. class Solution(object): def rob(self, nums): ...
- [LeetCode]House Robber II (二次dp)
213. House Robber II Total Accepted: 24216 Total Submissions: 80632 Difficulty: Medium Note: Thi ...
随机推荐
- 【分布式】Zookeeper服务端启动
一.前言 前面已经了解了Zookeeper会话相关知识点,接着来学习Zookeeper服务端相关细节. 二.服务端 服务端整体架构如下 Zookeeper服务器的启动,大致可以分为以下五个步骤 1. ...
- 如果你也会C#,那不妨了解下F#(4):了解函数及常用函数
函数式编程其实就是按照数学上的函数运算思想来实现计算机上的运算.虽然我们不需要深入了解数学函数的知识,但应该清楚函数式编程的基础是来自于数学. 例如数学函数\(f(x) = x^2+x\),并没有指定 ...
- Kafka无消息丢失配置
Kafka到底会不会丢数据(data loss)? 通常不会,但有些情况下的确有可能会发生.下面的参数配置及Best practice列表可以较好地保证数据的持久性(当然是trade-off,牺牲了吞 ...
- 支持多返回值存储过程的SqlHelper
public readonly string connStr = ConfigurationManager.ConnectionStrings["sql"].ConnectionS ...
- 运用css,对于下拉菜单的制作
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <met ...
- JDK1.7.0_45源码阅读<java.lang.Boolean>
本文适合的人群 其实感觉写这个标题的内容没有必要,只要你觉得对你有帮助那么就适合你,对你没帮助那么就不适合你.毕竟我不是专业作者,但咱会尽力的.其实最重要的一点是我不希望浪费您宝贵时间. 简要把内容在 ...
- 3.2 js六大数据类型
js中有六种数据类型,包括五种基本数据类型(Number,String,Boolean,Null,Undefined),和一种混合数据类型(Object). 前面说到js中变量是松散类型的,因此有时候 ...
- 原生JS实战:写了个一边玩游戏,一边记JS的API的游戏
本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5878913.html 本程序[一边玩游戏,一边记JS的API]是本人的个 ...
- 沙盒解决方案解决SharePoint 2013 以其他身份登陆的问题
众所周知,SharePoint 2013没有像SharePoint 2010那样有一个叫"以其他身份登录"的菜单项. 当然解决方案也很多,比如你可以直接修改Welcome.ascx ...
- 【搬砖】安卓入门(2)- Java开发编程基础--进制转换和运算符
02.01_Java语言基础(常量的概述和使用)(掌握) A:什么是常量 在程序执行的过程中其值不可以发生改变 B:Java中常量的分类 字面值常量 自定义常量(面向对象部分讲) C:字面值常量的分类 ...