题目描述:你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:
输入: [2,7,9,3,1]
输出: 12
解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。
解题思路: 动态规划
1.如果只有一间房,只能偷窃这一个房子,最大金额为改偷窃金额。
2.如果有二间房,因为不能偷相邻的两间房,所以只能偷这两间房中金额较大的房间。
3.如果房间数大于2呢(K > 2)
⑴ 偷窃第K个房间,就不能偷窃K - 1 的房间,能偷窃的总金额为 前K - 2的最大金额 与 第K个房间之和。
⑵ 不偷窃第K个房间,那么总金额就为前 K - 1 个房间的最大总金额。
总金额为这两项的较大那个值。states[i] = max(states[i - 1], states[i - 2] + nums[i]);
时间复杂度为O(n),空间复杂度为O(n)。
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if(n == 0)
return 0;
if(n == 1)
return nums[0];
vector<int> states = vector<int> (n,0);
states[0] = nums[0];
states[1] = max(nums[0], nums[1]);
for(int i = 2; i < n; ++i)
{
states[i] = max(states[i - 1], states[i - 2] + nums[i]);
}
return states[n - 1];
}
};
优化 动态规划 + 滚动数组
1.first 为 偷第K个房间,能偷窃的总金额为 前K - 2的最大金额 与 第K个房间之和。
2.second 为 不偷第K个房间,前 K - 1 个房间最大金额。
时间复杂度为O(n),空间复杂度为O(1)。
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if(n == 0)
return 0;
if(n == 1)
return nums[0];
vector<int> states = vector<int> (n,0);
int first = nums[0];
int second = max(nums[0], nums[1]);
for(int i = 2; i < n; ++i)
{
int temp = second;
second = max(second, first + nums[i]);
first= temp;
}
return second;
}
};