第四十天 第九章 动态规划part07 198.打家劫舍 213.打家劫舍II 337.打家劫舍III

 198.打家劫舍    

1.dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。

2.有递推公式可知,我们要先定义前面两个值。dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);

3.由于dp[i]是由前面两个推来的,所以遍历要从前到后。

class Solution {
public:
    int rob(vector<int>& nums) {
        vector<int> dp(nums.size());
        if(nums.size()==0) return 0;
        if(nums.size()==1) return nums[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[nums.size()-1];
    }
};

213.打家劫舍II  

这道题目和上面那题是差不多的,唯一区别就是成环了。

成环就考虑三种情况:

1.不含首尾元素         2.不含首个元素         3.不含尾部元素   

第二三种情况包含了第一种情况,所以我们只需处理第二三两种情况就可以了。

处理方法和上题差不多。

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

337.打家劫舍III  

这题融合了递归三部曲和动规五部曲。(这题很重要)也就是树形DP。

1.终止条件:当root==NULL时,偷与不偷都是0,也相当于初始化。

2.dp数组下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。

3.首先明确的是使用后序遍历。 因为要通过递归函数的返回值来做下一步计算。

class Solution {
public:
    int rob(TreeNode* root) {
      vector<int> res=traversal(root);   
      return max(res[0],res[1]);
    }
    vector<int> traversal(TreeNode *root){
        if(root==nullptr) return vector<int> {0,0};
        vector<int> left  = traversal(root->left);
        vector<int> right = traversal(root->right);
        int val1 = max(left[0],left[1])+max(right[0],right[1]);  //不偷    
        int val2 = root->val + left[0] + right[0];   //偷
        return {val1,val2};        
    }
};

  • 13
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值