自学内容网 自学内容网

代码随想录训练营第40天 198打家劫舍 213打家劫舍II 337打家劫舍III

第一题:

原题链接:198. 打家劫舍 - 力扣(LeetCode)

思路:

dp数组的含义:dp[i]表示偷到i号房屋的时候的最高金额。

由题意可知递推公式:dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])

初始化:dp[0] = nums[0], dp[1]为前两个数值的较大者;

遍历顺序从前往后遍历即可;

代码如下:

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

第二题:

原题链接:213. 打家劫舍 II - 力扣(LeetCode)

思路:

就是在上一题的基础上控制一下数组的范围,因为是环形的,首尾元素不能同时取,因此要划分为两个区间[0, n - 2] , [1, n - 1];

其他代码和上题很像,在自定义函数中要添加两个参数,起始位置和终止位置。

在函数的开始要注意的是如果起始位置和终止位置是相等的话就直接返回nums[start];

代码如下:

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

第三题:

原题链接:337. 打家劫舍 III - 力扣(LeetCode)

思路:

树形dp

树形结构采用后序遍历的方式,从下向上返回结果,

在自定义的函数里返回值为一个vector,其中有两个值,分别为dp[0]和dp[1], dp[0]表示当前节点不偷所得到的金钱,dp[1]表示当前节点偷所得到的金钱。

确定遍历顺序:

后序遍历:左右中,先一直向左遍历和向右遍历再向上返回结果。

通过递归左节点,得到左节点偷与不偷的金钱。

通过递归右节点,得到右节点偷与不偷的金钱。

单层递归逻辑:

如果是偷当前节点,那么左右孩子就不能偷,val1 = cur->val + left[0] + right[0]; (如果对下标含义不理解就再回顾一下dp数组的含义

如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);

最后当前节点的状态就是{val2, val1}; 即:{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}

代码如下:

/**
 * 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 {
public:
    int rob(TreeNode* root) {
        vector<int> res;
        res = robtree(root);
        return max(res[0], res[1]);
    }
private:
    vector<int> robtree(TreeNode* root){
        if(root == nullptr) return {0, 0};
        vector<int> leftdp = robtree(root -> left);
        vector<int> rightdp = robtree(root -> right);
        int val1 = root -> val + leftdp[0] + rightdp[0];
        int val2 = max(leftdp[0], leftdp[1]) + max(rightdp[0], rightdp[1]);
        return {val2, val1};
    }
};


原文地址:https://blog.csdn.net/weixin_44593575/article/details/140507942

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!