力扣---打家劫舍

打家劫舍的题目逐层递进,对应的数据结构为数组,环形数组,二叉树:
打家劫舍I — 数组
打家劫舍II — 环形数组
打家劫舍III — 二叉树
这个题目都有一个特点,即相邻两个屋不能都被偷窃,否则会触发警报。很明显每个屋有两种状态:偷或不偷。

  1. 确定dp数组
    dp[i] : 不偷 第 i 屋 或 偷第 i 屋 所得的最高金额
  2. 确定递推公式:后一个屋的结果由前两个屋得出,或父节点的结果由两个子树得出。
    dp[i] = max(dp[i-2]+nums[i], dp[i-1]);
    // 偷:则 i-1 屋不能偷,从i-2屋推过来;不偷:i-1 的结果即为该屋的结果
  3. dp 数组初始化
    dp[0] = nums[0]; // 第 0 屋肯定偷的金额最多
    dp[1] = max(nums[0], nums[1]); // 第 1 屋 则比较 0 和 1 屋的金额哪个更多
  4. 确定遍历顺序 :显然从前往后推导

打家劫舍II — 环形数组
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

这题的房屋首尾相连,则偷了 0 屋便一定不能偷最后一个屋(n-1); 偷了 n-1 屋,便一定不能偷 0 屋。
if (nums.size() == 1)
    return nums[0];
if (nums.size() == 2)
    return max(nums[0], nums[1]);
// 不计nums[0],即偷 n-1 屋,相当于 0 屋不存在
vector<int>dp1(nums.size()-1, 0);
dp1[0] = nums[1];
dp1[1] = max(nums[1], nums[2]);
for (int i=3; i<nums.size(); ++i) {
    dp1[i-1] = max(dp1[i-3]+nums[i], dp1[i-2]);
}
// 不计nums[n-1],即偷 0 屋,相当于 n-1 屋不存在
vector<int>dp2(nums.size()-1, 0);
dp2[0] = nums[0];
dp2[1] = max(nums[0], nums[1]);
for (int i=2; i<nums.size()-1; ++i) {
    dp2[i] = max(dp2[i-2]+nums[i], dp2[i-1]);
}
return max(dp1[nums.size()-2], dp2[nums.size()-2]);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值