代码随想录 第九章 动态规划part07 198.打家劫舍 213.打家劫舍II 337.打家劫舍III

198.打家劫舍

class Solution {
public:
    int rob(vector<int>& nums) {
        vector<int> dp(nums.size() + 1, 0);
        nums.insert(nums.begin(), 0);
        dp[1] = nums[1];
        int pre = 1;
        for (int i = 2; i < dp.size(); i++){
            if (pre == (i - 1)){
                if (dp[i - 1] < dp[i - 2] + nums[i]){
                    dp[i] = dp[i - 2] + nums[i];
                    pre = i;
                }else{
                    dp[i] = dp[i - 1];
                }
            }else{
                dp[i] = dp[i - 1] + nums[i];
                pre = i;
            }
        }
        for(int i=0;i<nums.size();i++){
            cout<<dp[i]<<" ";
        }
        return dp[nums.size() - 1];
    }
};

这题笔者一开始没看题解,有些想得太复杂了,考虑了上一个打劫的是不是与当前位置相邻,看了题解之后发现其实不需要知道是否相邻,dp[i-2]打劫的不会与i相邻,而dp[i-1]可能与打劫过的可能与i相邻,所以只需要取dp[i-1]与dp[i-2]+nums[i]两者的最大值即可。

213.打家劫舍II

class Solution {
private:
    int robrange(vector<int> nums, int start, int end){
        vector<int> dp(nums.size(), 0);
        dp[start] = nums[start];
        for (int i = start + 1; i < end; i++){
            dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]);
        }
        return dp[end - 1];
    }
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 1) return nums[0];
        nums.insert(nums.begin(), 0);
        int result1 = robrange(nums, 1, nums.size()-1);
        int result2 = robrange(nums, 2, nums.size());
        return max(result1, result2);
    }
};

这题一开始笔者以为或许会给出一种只需遍历一遍即可的方案,看了题解之后发现就是一次掐头一次去尾,遍历两次取最大值。

337.打家劫舍III

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    vector<int> robtree(TreeNode* root){
        if (root == NULL) return {0, 0};
        vector<int> left = robtree(root->left);
        vector<int> right = robtree(root->right);
        vector<int> result(2, 0);
        result[0] = left[1] + right[1] + root->val;
        result[1] = max(left[0], left[1]) + max(right[0], right[1]);
        return result;
    }
public:
    int rob(TreeNode* root) {
        vector<int> result = robtree(root);
        return max(result[0], result[1]);
    }
};

这题难的地方在于一个节点可能有3个邻接,就不能再用之前的方法了。随想录给的题解是自底向上,求取对当前节点来说,打劫与不打劫的最大值,在递归中,每个节点会向上传递两个值,一个是打劫当前节点的最大值,一个是不打劫当前节点的最大值,前者意味着不能打劫左右子节点,所以直接利用子节点得出的不打劫子节点的最大值计算,后者代表子节点可以被打劫也可以不被打劫,比对子节点得出的被打劫与不被打劫的最大值计算即可,一次类推,即可得到答案。

代码随想录 第九章 动态规划part07

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值