代码随想录训练营Day34:背包问题解决打家劫舍

1.198打家劫舍

1.dp数组的含义:dp[i]表示从第零个偷到第i个能够偷到的最大价值。

2.递推公式:分成两种情况:

  1. 偷第i个的情况下的最大值,注意此时第i-1个肯定是不偷的,所以此时dp[i] = dp[i-2]+nums[i];=>dp[j] = dp[j-weight[i]]+value[i];
  2. 不偷第i个的情况下的最大值,需要注意的是此时第i-1个不一定偷,只是考虑第i-1个房间。所以此时为dp[i] = dp[i-1]

最后取两者的最大值。

复制代码
class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        if(n == 0)return 0;
        if(n == 1) return nums[0];//边界条件
        vector<int> dp(n);//偷到i房间的最大的价值
        dp[0] = nums[0];
        dp[1] = max(nums[0],nums[1]);
        for(int i = 2;i<n;i++){
            //偷第i个房间:第i-2最大值的最大值加上当前的值,不偷第i个房间:第i-1的最大值
            dp[i] = max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[n-1];
    }
};

2.213打家劫舍二

本题相比于前面多了一个首尾相连的情况,为了解决这个问题,我们可以将其分成两个部分(第一个是不含最后一个,第二个是不含第一个),每个部分都按按照前面打家劫舍的方式来求解,求解出两种情况下打家劫舍的最大值之后,然后计算出最大值即可。

复制代码
class Solution {
public:
    int rob(vector<int>& nums) {
        //分成两次,一次是含首不含尾,一次是含尾不含首,两次求出来的最大值再最后求一个最大值即为最终结果
        int n = nums.size();
        if(n==1) return nums[0];
        if(n==2) return max(nums[0],nums[1]);
        //vector<int> dp1(n-1);
        int dp10 =nums[0],dp11=max(nums[0],nums[1]),result1=dp11;
        int dp20 =nums[1],dp21=max(nums[1],nums[2]),result2=dp21;
        for(int i = 2;i<n-1;i++){
            result1 = max(dp10+nums[i],dp11);
            dp10 = dp11;
            dp11 = result1;
            result2 = max(dp20+nums[i+1],dp21);
            dp20 = dp21;
            dp21 = result2;
        }
        return max(result1,result2);
        /*dp1[0]=nums[0];
        cout<<dp1[0];
        dp1[1]=max(nums[0],nums[1]);
        for(int i = 2;i<n-1;i++){
            dp1[i]=max(dp1[i-2]+nums[i],dp1[i-1]);
        }
        vector<int> dp2(n-1);
        dp2[0]=nums[1];
        dp2[1]=max(nums[1],nums[2]);
        for(int i = 2;i<n-1;i++){
            dp2[i]=max(dp2[i-2]+nums[i+1],dp2[i-1]);
        }
        return max(dp1[n-2],dp2[n-2]);*/
    }
};

3.337打家劫舍三

思路:首先我们可以看出这是一个树形结构,对于这种树形结构要求出最大值,我们就需要先确定遍历顺序,先确定左右两个孩子是否偷,再确定父节点是否偷从而实现一个相对来说的最大值,所以遍历方式选择的是深度遍历。第二个需要确定的就是返回值:由于偷和不偷分为两种情况,所以返回值应该是一个数组,分别存放偷还是不偷的结果。第三个确定的是循环终止条件:当其孩子节点为空的时候,偷不偷都是0,此时返回return {0,0};第四个需要确定的是循环内的处理情况:分别是该节点偷的时候的最大值和该节点不偷的时候的最大值,将其作为返回数组返回。

复制代码
/**
 * 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:
    //[不偷,偷]这样的返回结果
    vector<int> TreerobMax(TreeNode* cur){
        if(cur == nullptr){
            return {0,0};
        }
        vector<int> left = TreerobMax(cur->left);
        vector<int> right = TreerobMax(cur->right);
        //第一种情况偷
        int val1 = cur->val + left[0]+right[0];
        //第二种情况不偷
        int val2 = max(left[0],left[1])+max(right[0],right[1]);
        return {val2,val1};
    }
    int rob(TreeNode* root) {
        vector<int> result = TreerobMax(root);
        return max(result[0],result[1]);
    }
};
相关推荐
qq_386322691 分钟前
华为-AI智算网络学习-1
学习
武文斌775 分钟前
PCB画板:电阻、电容、电感、二极管、三极管、mos管
单片机·嵌入式硬件·学习
CoovallyAIHub14 分钟前
告别碎片化!Dinomaly2:一个极简框架统一所有异常检测任务
深度学习·算法·计算机视觉
Watermelo61722 分钟前
从vw/h到clamp(),前端响应式设计的痛点与进化
前端·javascript·css·算法·css3·用户界面·用户体验
让我们一起加油好吗26 分钟前
【数论】乘法逆元(求逆元的三种方式)
算法·数论·费马小定理·扩展欧几里得算法·乘法逆元
sigd30 分钟前
排队选人-2024年秋招-小米集团-软件开发岗-第二批笔试
数据结构·算法
魔猴疯猿32 分钟前
将地球上的距离转化为经纬度差
算法·距离转化·经纬度差
高洁0138 分钟前
大模型-详解 Vision Transformer (ViT)
人工智能·python·深度学习·算法·transformer
天选之女wow1 小时前
【代码随想录算法训练营——Day58】图论——117.软件构建、47. 参加科学大会
算法·图论
charlie1145141911 小时前
CSS学习笔记6:定位与布局
前端·css·笔记·学习·css3·教程