213. 打家劫舍 II

在这里插入图片描述
聪明的小偷系列,和打家劫舍1一样,记录dp[i-1]和i-1之前能偷到的最大总和。因为是个环,所以我们进行两次dp,从0到n-1和1到n,记录下能偷到更大的那个值即可

class Solution {
public:
    int rob(vector<int>& nums) {
        //第一间房和最后一间房只能偷一个,dp两次,分别dp的是偷第一间房和偷到倒数第二间以及不偷第一间房偷到最后一间
       if(nums.size() == 0) return 0;
       if(nums.size() == 1) return nums[0];
       if(nums.size() == 2) return max(nums[0],nums[1]);
       //偷第一间,maxn记录的是除当前房间前一外能偷到的最大值
       int maxn = nums[0], pre = nums[1];
       int res = max(maxn,pre);
       for(int i = 2; i < nums.size()-1; ++i){
           res = max(maxn+nums[i],pre);
           maxn = max(maxn,pre);
           pre = res;
       }
       int res1 = res;
       maxn = nums[1];
       pre = nums[2];
       for(int i =3; i < nums.size(); ++i){
           res = max(maxn+nums[i],pre);
           maxn = max(maxn,pre);
           pre = res;
       }
       return max(res1,res);
    }
};

pre记录的是偷或者不偷前一间能得到的最大值,maxn是除了前一间能偷到的最大值,因为不一定是前两间,有可能隔着2间。

class Solution {
public:
    int rob(vector<int>& nums) {
        //紧挨着的,所以第一个和最后一个不能连续偷
        //这道题的dp不是普通的记录前两个,而是记录dp[i-1]和不偷nums[i-1]能得到的最大值,因为如果是[1,2,1,1,2]这样的,两个2中间隔了两个也可能得到最大值
        if(nums.size() == 1) return nums[0];
        //为了防止只有两个数,我们进行第二次dp的时候会越界,所以提前判断
        if(nums.size() == 2) return max(nums[0],nums[1]);
        int maxn = nums[0], pre = nums[1];
        int res1 = max(pre,maxn);
        //pre是dp[i-1]
        for(int i = 2; i < nums.size()-1; ++i){
            res1 = max(maxn+nums[i],pre);
            maxn = max(pre,maxn);
            pre = res1;//更新dp[i-1]为dp[i]
        }
        pre = nums[2], maxn = nums[1];
        int res2 = max(pre,maxn);
        for(int i = 3; i < nums.size(); ++i){
            res2 = max(maxn+nums[i],pre);
            maxn = max(pre,maxn);
            pre = res2;
        }
        return max(res1,res2);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值