题目大意
你要去一条街上偷钱,每一户人家都有一定量的钱,但是你不能偷相邻两家的,因为相邻的两家有安保系统相连,偷了你就被警察叔叔带走了(什么鬼安保系统= =)。
给定一个非负数组,代表每家有多少钱。求出在不被警察叔叔带走的情况下,你今晚最多能偷多少钱。
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.
class Solution {
public:// f[0] = nums[0] f[1]=max(nums[0],nums[1]) f[2]=max(f[1],f[0]+nums[i])
int rob(vector<int>& nums) {
int size = nums.size();
if (size == 0){
return 0;
}
else if(size == 1){
return nums[0];
}else if(size == 2){
return max(nums[0],nums[1]);
}
vector<int> f(size,0);
f[0] = nums[0];
f[1] = max(nums[0],nums[1]);
for(int i=2;i<size;++i){
f[i]=max(f[i-2]+nums[i],f[i-1]);
}
return f[size-1];
}
};
/*
思路:因为不能抢劫挨着的店家, 所以这道题的本质相当于在一列数组中取出一个或多个不相邻数,使其和最大,使用dp。 举例子{1,2,3,4}, f[i]表示到第i家能偷窃的最大钱数,f[0] = nums[0], f[1] = max(nums[0], nums[1]), f[2]有两种可能,就是只取f[1]或者取f[0] + f[2]. 所以递推公式是:
f[i] = Math.max(f[i - 2] + nums[i], f[i - 1]);
时间复杂度: O(n)
空间复杂度: O(n)
public class Solution {
public int rob(int[] nums) {
if (nums.length == 0 || nums == null) {
return 0;
}
int[] f = new int[nums.length];
f[0] = nums[0];
if (nums.length == 1) {
return f[0];
}
f[1] = nums[0] > nums[1] ? nums[0] : nums[1];
if (nums.length == 2) {
return f[1];
}
for (int i = 2; i < nums.length; i++) {
f[i] = Math.max(f[i - 2] + nums[i], f[i - 1]);
}
return f[nums.length - 1];
}
}
空间改进
由递推数组可以看出,并不需要n个空间,所以我们用滚动数组
时间复杂度:O(n)
空间复杂度:O(1)
public class Solution {
public int rob(int[] nums) {
if (nums.length == 0 || nums == null) {
return 0;
}
int[] f = new int[3];
f[0] = nums[0];
if (nums.length == 1) {
return f[0];
}
f[1] = nums[0] > nums[1] ? nums[0] : nums[1];
if (nums.length == 2) {
return f[1];
}
for (int i = 2; i < nums.length; i++) {
f[i % 3] = Math.max(f[(i - 2) % 3] + nums[i], f[(i - 1) % 3]);
}
return f[(nums.length - 1) % 3];
}
}
*/