动态规划---打家劫舍

说明

打家劫舍问题算是动态规划问题中的一个小分支,这里单独写一篇文章介绍,需要注意的是,本片文章没有很详细的讲解,仅仅做一个汇总作用。至于动态规划问题除了处理的详细步骤我在我的另一篇文章中详细介绍过。具体解决步骤请移步观看——动态规划基础篇

例题讲解

1.打家劫舍

1.1题目详情

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 400
1.2一维dp
class Solution {
    public int rob(int[] nums) {

        if(nums.length==1) return nums[0];
        if(nums.length==2) return Math.max(nums[0],nums[1]);

        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        dp[1]=Math.max(nums[0],nums[1]);

        for(int i=2;i<nums.length;i++){
            dp[i]=Math.max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[nums.length-1];
    }
}

1.3空间优化
class Solution {
    public int rob(int[] nums) {

        if(nums.length==1) return nums[0];
        if(nums.length==2) return Math.max(nums[0],nums[1]);
        int a=nums[0];
        int b=Math.max(nums[0],nums[1]);
        int c=0;
        for(int i=2;i<nums.length;i++){
            c=Math.max(a+nums[i],b);
            a=b;
            b=c;
        }
        return c;
    }
}

2.打家劫舍||

2.1题目详情

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 1000
2.2

public class Solution {
    public int rob (int[] nums) {
        // write code here
        if(nums.length==1) return nums[0];
        if(nums.length==2) return Math.max(nums[0],nums[1]);

        int val1=robTree(nums,0,nums.length-2);
        int val2=robTree(nums,1,nums.length-1);

        return Math.max(val1,val2);
    }

    public int robTree(int[] nums,int start,int end){
        if(end-start==1) return Math.max(nums[start],nums[end]);

        int a=nums[start];
        int b=Math.max(nums[start],nums[start+1]);
        int c=0;
        for(int i=start+2;i<=end;i++){
            c=Math.max(a+nums[i],b);
            a=b;
            b=c;
        }

        return c;

    }
}

3.打家劫舍|||

3.1题目详情

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。

除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
在这里插入图片描述

提示:

  • 树的节点数在 [1, 104] 范围内
  • 0 <= Node.val <= 104
3.2 动态规划+递归
class Solution {
    /**
       robTree(TreeNode cur):返回一个长度为2的一维数组res,
       res[0]:不偷该节点所得的最大金钱
       res[1]:偷该节点所得的最大金钱
    
     */

    public int rob(TreeNode root) {
       int[] res=robTree(root);
       return Math.max(res[0],res[1]);
    }

    public int[] robTree(TreeNode cur){
        //当前节点为空:返回值都为0的数组
        if(cur==null) return new int[2];

        int[] left=robTree(cur.left);
        int[] right=robTree(cur.right);

        //val1:表示偷当前节点,那么根据题意可知,其左右子节点都不能偷
        int val1=cur.val+left[0]+right[0];

        //val2:表示不偷当前节点,那么根据题意可知,其左右子节点都可以偷,但不一点必须要偷
        int val2=Math.max(left[0],left[1])+Math.max(right[0],right[1]);

        int[] res=new int[2];
        res[0]=val2;
        res[1]=val1;
        return res;
    }
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
打家劫舍是一个经典的动态规划问题。根据引用\[2\]中的解法,我们可以使用动态规划来解决这个问题。假设偷窃房屋的下标范围是\[start, end\],用dp\[i\]表示在下标范围\[start, i\]内可以偷窃到的最高总金额。根据状态转移方程dp\[i\] = max(dp\[i − 2\] + nums\[i\], dp\[i − 1\]),我们可以通过递推得到最终的结果。 在解决这个问题时,我们可以使用滚动数组来降低空间复杂度,只需要存储前两间房屋的最高总金额,将空间复杂度降到O(1)。具体的代码实现可以参考引用\[2\]中的代码。 另外,对于打家劫舍 III这个问题,根据引用\[3\]中的解法,我们可以使用递归的方式来解决。对于每个节点,我们可以选择偷取该节点的钱和其四个孙子节点的钱,或者选择偷取其两个儿子节点的钱,然后比较两种方案的钱数,选择钱数较多的方案作为当前节点能偷取的最大钱数。 具体的代码实现可以参考引用\[3\]中的代码。 综上所述,我们可以使用动态规划来解决打家劫舍问题,具体的解法可以参考引用\[2\]中的代码。对于打家劫舍 III这个问题,可以使用递归的方式来解决,具体的解法可以参考引用\[3\]中的代码。 #### 引用[.reference_title] - *1* *2* *3* [动态规划解决打家劫舍问题](https://blog.csdn.net/p1967914901/article/details/125372599)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上阡陌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值