力扣-198-打家劫舍
直达链接
2022/10/28 重做
要求是不触发报警,即:对数组中的元素不相邻选中的情况下,能够获得的最大和
int rob(vector<int>& nums) {
// 定义一个dp数组dp[i]代表截至i(包括)能够获得的最大金额
// 对于任意nums[i],如果这户要偷,则上一户一定不偷dp[i] = dp[i-2]+nums[i]
// 如果这户不偷,dp[i] = dp[i-1]
int n = nums.size();
vector<int> dp(n + 1);
// 照上面的看来我至少要初始化2个元素
dp[0] = 0, dp[1] = nums[0];
for (int i = 2; i <= n; i++) dp[i] = max(dp[i - 1], dp[i - 2] + nums[i-1]);
return dp[n];
}
然后做空间优化,这里需要三个变量,然后这里循环也可以改一下,看着有点别扭
int rob(vector<int>& nums) {
int prepre = 0, pre = nums[0], cur = nums[0];
for (int i = 1; i < nums.size(); i++) {
cur = max(pre, prepre + nums[i]);
prepre = pre;
pre = cur;
}
return cur;
}
我再想这个题有没有可能就是比奇数序列和偶数序列哪个大
int rob(vector<int>& nums) {
int odd = 0,even = 0;
for (int i = 0; i < nums.size(); i++) {
if (i % 2) odd += nums[i];
else even += nums[i];
}
return max(odd,even);
}
哈哈,好吧,不是这样的
思路
当我们打劫到一个房子i的时候,有两种选择
- 不打劫这栋房子,那么总收益就是dp[i-1],即打劫到上一栋房子的收益
- 打劫这栋房子,同时有不能打劫相邻房子的限制,则总收益为:dp[i]+dp[i-2]
状态转移方程为:dp[i]=max(dp[i-1],input[i]+dp[i-2])
代码
class Solution {
public:
int rob(vector<int>& nums) {
// nums.length>=1,就是说一定不为空,否则就要判断
int len = nums.size();
// 分析初始值:如果只有1栋房子,那么最高收益一定就是nus[0]
// if (len == 1) return nums[0];
// 这句不需要,下面的代码能包含这种情况,但是或许能剪枝?跑一跑还是去掉效率高一点
int pre1 = 0, pre2 = 0, cur;
// 如果是第二栋,是第一栋与第二栋的最大值,就可以开始
for (int i = 0; i < len; ++i) {
// 这里<len主要影响的是nums的下标
cur = max(pre1, pre2 + nums[i]);
pre2 = pre1;
pre1 = cur;
}
return cur;
}
};
效率很不错