leetcode——打家劫舍问题汇总

        本章汇总一下leetcode中的打家劫舍问题,使用经典动态规划算法求解。

1、梦开始的地方——打家劫舍(★)

         本题关键点就是不能在相邻房屋偷东西

采用常规动态规划做法:

  • 根据题意设定dp数组,dp[i]的含义为:前i个房屋内,能偷的最高金额。
  • 需要初始化dp[0]=0,dp[1]=nums[0]。
  • 遍历dp数组,对应两种情况:偷或者不偷。 递推公式为:
    • dp[i] = Math.max(dp[i-1] , dp[i-2]+nums[i-1]);

  • 最后返回dp数组最后一个数。

java代码如下:

class Solution {
    public int rob(int[] nums) {
        if(nums.length == 1) return nums[0];
        int[] dp = new int[nums.length+1]; //dp[i]:前i个房屋内,能偷的最高金额。
        dp[1] = nums[0];
        for(int i=2; i<=nums.length; i++){
            dp[i] = Math.max(dp[i-1] , dp[i-2]+nums[i-1]); //分别对应偷或者不偷
        }
        return dp[nums.length];
    }
}

2、打家劫舍II

        本题是上一题的进阶版,区别在于收尾两个房屋也是相邻的,不能同时偷。  此时无非就两种情况:

  • 不偷首房屋。
  • 不偷尾房屋。

        分别设两个dp数组对应以上两种情况即可,思路还是类似上一题

java代码如下:

class Solution {
    public int rob(int[] nums) {
        if(nums.length == 1) return nums[0];
        int[] dp1 = new int[nums.length]; //不偷首房屋
        int[] dp2 = new int[nums.length]; //不偷尾房屋
        dp1[1] = nums[1];
        dp2[1] = nums[0];
        for(int i=2; i<nums.length; i++){
            dp1[i] = Math.max(dp1[i-1] , dp1[i-2]+nums[i]);
            dp2[i] = Math.max(dp2[i-1] , dp2[i-2]+nums[i-1]);
        }
        return dp1[nums.length-1] > dp2[nums.length-1] ? dp1[nums.length-1] : dp2[nums.length-1];
    }
}

3、打家劫舍III(★)

        本题是从数组型dp转化为树形dp,由于父节点的状态需要从孩子节点的状态推出来,因此需要使用后序遍历。 

        首先需要定义一个递归函数dfs,参数为当前节点,返回值为长度为2的数组,即dp数组,dp[0]代表选当场节点,dp[1]代表不选当前节点。 如下:

int[] dfs(TreeNode node)

         接下来确定终止条件

if(node == null) return new int[] {0,0};

        使用后序遍历递归遍历左右子树:

        //递归左右子树

        int[] left = dfs(node.left);

        int[] right = dfs(node.right);

        确定单层递归逻辑:

//分别对应偷与不偷的情况:        

int rob = node.val + left[1] + right[1];

int no_rob = Math.max(left[0],left[1]) + Math.max(right[0],right[1]);

        java代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int rob(TreeNode root) {
        int[] ans = dfs(root);
        return Math.max(ans[0],ans[1]);
    }
    private int[] dfs(TreeNode node){
        if(node == null) return new int[] {0,0};
        //递归左右子树
        int[] left = dfs(node.left);
        int[] right = dfs(node.right);
        int rob = node.val + left[1] + right[1];
        int no_rob = Math.max(left[0],left[1]) + Math.max(right[0],right[1]);
        return new int[] {rob,no_rob};
    }
}

 

相关推荐

  1. LeetCode 打家劫舍

    2023-12-30 19:54:03       27 阅读
  2. leetcode 打家劫舍 总结

    2023-12-30 19:54:03       38 阅读
  3. Leetcode 198 打家劫舍

    2023-12-30 19:54:03       26 阅读
  4. Leetcode 337 打家劫舍 III

    2023-12-30 19:54:03       21 阅读
  5. leetcode热题】打家劫舍

    2023-12-30 19:54:03       20 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-30 19:54:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-30 19:54:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-30 19:54:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-30 19:54:03       20 阅读

热门阅读

  1. 解决在Android Compose中点击空白处收回软键盘

    2023-12-30 19:54:03       34 阅读
  2. 第八周:AIPM面试准备

    2023-12-30 19:54:03       40 阅读
  3. 如何基于PyTorch框架自定义数据集类获取数据

    2023-12-30 19:54:03       37 阅读
  4. 设计模式之模板方法

    2023-12-30 19:54:03       35 阅读
  5. 【DB2】运行preprpnode的时候报错

    2023-12-30 19:54:03       37 阅读
  6. C++音视频开发技巧汇总(持续更新)

    2023-12-30 19:54:03       35 阅读
  7. Spring-IOC-xml方式

    2023-12-30 19:54:03       39 阅读
  8. 12.25

    12.25

    2023-12-30 19:54:03      37 阅读
  9. 鸿蒙OS应用开发之自定义弹窗

    2023-12-30 19:54:03       42 阅读