Leetcode (198)打家劫舍Ⅰ,(213)打家劫舍Ⅱ,(337)打家劫舍Ⅲ

打家劫舍Ⅰ

在这里插入图片描述
题意:线性房屋,不能偷盗相邻的两个屋子。要求偷到的总金额最高
题解: 设置一个滚动数组, l l l 为nums[0], r r r 为nums[0] , nums[1] 的最大值,maxx = max(l + nums[i], r) 这个就很灵性了。
举个例子,如果是[1,2,3]
那么在这个过程就是:

  1. l l l = nums[0] = 1
  2. r r r = max(nums[0], nums[1]) = max(1, 2) = 2
  3. maxx = max( l l l + nums[i], r r r) = max(nums[0] + nums[2], max(nums[0], nums[1]) ) = max(1 + 3, 1 + 2) = 4
class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 0) 
            return 0;
        if (nums.size() == 1) //如果长度为1,就只能偷一家
            return nums[0];
        //不能偷盗相邻的两家
        int l = nums[0];
        int r = max(nums[0], nums[1]); 
        int maxx = max(l, r);
        for (int i = 2; i < nums.size(); ++i) {
            maxx = max(l + nums[i], r);
            int tmp = r;
            r = maxx;
            l = tmp;
        }
        return maxx;
    }
};

用dp的方法就是:
找到转移方程:
d p [ i ] = m a x ( d p [ i − 2 ] + n u m s [ i ] , d p [ i − 1 ] ) dp[i]=max(dp[i−2]+nums[i],dp[i−1]) dp[i]=max(dp[i2]+nums[i],dp[i1])
考虑越界情况:
d p [ 0 ] = n u m s [ 0 ] dp[0]=nums[0] dp[0]=nums[0]
d p [ 1 ] = m a x ( n u m s [ 0 ] , n u m s [ 1 ] ) dp[1]=max(nums[0], nums[1]) dp[1]=max(nums[0],nums[1])

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 0) {
            return 0;
        }
        if (nums.size() == 1) {
            return nums[0];
        }
        vector<int> dp = vector<int>(nums.size(), 0);
        //越界情况
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);
        for (int i = 2; i < nums.size(); i++) {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        return dp[size - 1];
    }
};

打家劫舍Ⅱ
在这里插入图片描述
题意: 打家劫舍Ⅱ比打家劫舍Ⅰ多了一种情况, 环状情况,不能同时偷盗第一间和最后一间。
题解:
思路是:将环状的情况,转换为两条链状情况。
偷盗 1 1 1 ~ n − 1 n-1 n1 个房间的最大值以及偷盗 2 2 2 ~ n n n 个房间的最大值。
进行两次dp就可以了。
将二者最大值比较即可。

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 0) 
            return 0;
        if (nums.size() == 1) 
            return nums[0];
        vector<int> dp(nums.size() + 1);
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);
        for (int i = 2; i < nums.size() - 1; ++i) {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        int res = dp[nums.size() - 2];
        dp[0] = 0;
        dp[1] = nums[1];
        for (int i = 2; i < nums.size(); i++) {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        res = max(res, dp[nums.size() - 1]);
        return res;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值