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.
第一次提交的时候出现了这个错误:
Line 933: Char 34: runtime error: reference binding to null pointer of type 'value_type' (stl_vector.h)
Last executed input:[ ]
错误原因是当输入为空时,按照题意应当返回为空,但按照我所写的代码来运行,并不会是正确答案(应输出0),所以出错,要提前单独考虑输入为空的情况,同时这题还要考虑输入为1个值得情况,否则后面dp的实现也会因数组下标越界而出错
这里先强推一篇文章:【https://leetcode.com/problems/house-robber/discuss/156523/From-good-to-great.-How-to-approach-most-of-DP-problems.】暂且先不说是不是写的很好,但他的学习方法应当学习,虽然是英文,但句子都通俗易懂
正确解法: 时间复杂度为O(n)
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if(n == 0)//没有房子
return 0;
else if(n == 1)//只有一间房子
return nums[0];
vector<int> money(n+1, 0);//定义一个元素个数为n的vector,初值均为0
money[1] = nums[0];//第一间房子的钱
money[2] = nums[1];//第二间房子的钱
int temp;
for(int i = 3; i <= n; i++){
temp = money[i-2] > money[i-3] ? money[i-2] : money[i-3];
money[i] = temp + nums[i-1];
}
return max(money[n],money[n-1]);
}
};
Runtime: 0 ms, faster than 100.00% of C++ online submissions for House Robber.
【解析】(这里是重点)
for循环中的语句:
temp = money[i-2] > money[i-3] ? money[i-2] : money[i-3];
money[i] = temp + nums[i-1];
1 | 2 | 3 | 4 | 5 | 6 | ... | n |
【注意】这里编号x的房子并不是指该房子所有的金钱,而是当盗取完该编号的房子时,所能获得最大的金额数
先来看下上面这个表格,把每个格子看成是一个房子,编号为1、2、3...n
此时若for循环中的i = 6,接下来该考虑的是,当盗取第6个房子时,此时编号5的房子是肯定不可以偷取的(现在从前到后考虑,先不用管编号大于6的房子),那么就考虑编号为4和编号3的房子,但不用考虑编号2及编号2之前的房子,这是因为前面的房子无论金额大小如何都已经被编号4和编号3的房子考虑进去了,此时能使得当盗取完编号6的房子能获得最大金额的必定是以编号4和编号3中的金额为基础的,再加上编号6房子所拥有的金额的金额总数。