【代码随想录】Day 48 动态规划9 (打家劫舍Ⅰ Ⅱ Ⅲ)

打家劫舍

https://leetcode.cn/problems/house-robber/
在这里插入图片描述
注意要是i-1没偷,那么dp[i] = dp[i-2] + nums[i],而不是dp[i-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(nums.size());
        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.back();
    }
};

打家劫舍Ⅱ

https://leetcode.cn/problems/house-robber-ii/
在这里插入图片描述
环形问题展开为线形,分析几种情况:

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());
        vector<int> dp1(nums.size());
        vector<int> dp2(nums.size());
        //情况1 线性数组
        // dp[0] = 0;
        // dp[1] = nums[1];
        // for (int i = 2; i < nums.size()-1; i++) {
        //     dp[i] = max(dp[i-2] + nums[i], dp[i-1]);
        // }

        //情况2 不偷尾
        dp1[0] = nums[0];
        dp1[1] = max(nums[0], nums[1]);
        for (int i = 2; i < nums.size()-1; i++) {
            dp1[i] = max(dp1[i-2] + nums[i], dp1[i-1]);
        }
        //情况3 不偷头
        dp2[0] = 0;
        dp2[1] = nums[1];
        for (int i = 2; i < nums.size(); i++) {
            dp2[i] = max(dp2[i-2] + nums[i], dp2[i-1]);
        }
        return max(dp1[nums.size()-2], dp2.back());
    }
};

打家劫舍Ⅲ

https://leetcode.cn/problems/house-robber-iii/
在这里插入图片描述
大名鼎鼎的树形dp入门题,确实没做过的话完全想不到。。。
遍历树的节点的时候有两种情况,不偷自己和偷自己:robSelf[0]和robSelf[1],分别记录两种情况得到的最大金额。
注意偷自己的时候,两个孩子都属于不能偷的状态,所以robSelf[1] = self->val + left[0] + right[0];不偷自己的时候,两个孩子都能偷,所以可以偷他们俩最大值的和:robSelf[0] = max(left[0],left[1]) + max(right[0], right[1]);

class Solution {
public:
    vector<int> robTree(TreeNode* root) {
        vector<int> robSelf(2);        
        if (root == nullptr) return robSelf;
        
        //后序遍历 左右中
        vector<int> left = robTree(root->left);
        vector<int> right = robTree(root->right);

        //0不偷自己,偷俩孩子的和, 1偷自己,孩子都不能偷
        robSelf[0] = max(left[0], left[1]) + max(right[0], right[1]);
        robSelf[1] = root->val + left[0] + right[0];

        return robSelf;   
    }

    int rob(TreeNode* root) {
        vector<int> robSelf = robTree(root);
        return max(robSelf[0], robSelf[1]);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值