代码随想录打卡第五十天|198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III

198.打家劫舍

题目:
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
题目链接: 198.打家劫舍
代码如下:

class Solution {
    //dp[n][0] 表示偷n号房屋时前n个房屋可偷的最大值
    //dp[n][1] 表示不偷n号房屋时前n个房屋可偷的最大值
    public int rob(int[] nums) {
        int n=nums.length;
        int[][] dp=new int[n+1][2];
        dp[1][0]=nums[0];
        dp[1][1]=0;
        for(int i=2;i<=n;i++){
            dp[i][0]=dp[i-1][1]+nums[i-1];
            dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]);
        }
        return Math.max(dp[n][0],dp[n][1]);
    }
}

相关题目: 乘积最大子数组

213.打家劫舍II

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

class Solution {
    public int rob(int[] nums) {
        //第一间房屋和最后一间不能同时偷
        //从0到n-1 和从1到n遍历一遍 求最高金额
         if (nums == null || nums.length == 0)
            return 0;
        int len = nums.length;
        if (len == 1)
            return nums[0];
        int left=robAction(nums,0,nums.length-1);
        int right=robAction(nums,1,nums.length);
        return Math.max(left,right);
    }
    int robAction(int[] nums, int start, int end) {
        int x = 0, y = 0, z = 0;
        for (int i = start; i < end; i++) {
            y = z;
            z = Math.max(y, x + nums[i]);
            x = y;
        }
        return z;
    }
}

337.打家劫舍III 树形dp!

题目: 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。给定二叉树的 root 。返回在不触动警报的情况下 ,小偷能够盗取的最高金额 。
代码随想录打卡第五十天|198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III_第1张图片
代码随想录打卡第五十天|198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III_第2张图片

题目链接: 337.打家劫舍III
解法1:树形dp

class Solution {
    //dp[0] 为偷 dp[1] 为不偷 因为是递归所以不需要遍历


    public int rob(TreeNode root) {
        //后序遍历
        int [] res=track(root);
        return Math.max(res[0],res[1]);
        
    }
    public int[] track(TreeNode root){
        int[] dp=new int[2];
        if(root==null){
            return dp;
        }
        int[] left=track(root.left);
        int[] right=track(root.right);
        dp[0]=root.val+left[1]+right[1];
        dp[1]=Math.max(left[0],left[1])+Math.max(right[0],right[1]);
        return dp;
    }
}

解法2:暴力解法与记忆化搜索

class Solution {
    // 1.递归去偷, 比较偷爷孙和偷儿子的最大值
    public int rob(TreeNode root) {
        if (root == null)
            return 0;
        int money = root.val;
        if (root.left != null) {
            money += rob(root.left.left) + rob(root.left.right);
        }
        if (root.right != null) {
            money += rob(root.right.left) + rob(root.right.right);
        }
        return Math.max(money, rob(root.left) + rob(root.right));
    }

    // 2.递归去偷,记录状态
    // 执行用时:3 ms , 在所有 Java 提交中击败了 56.24% 的用户
    public int rob1(TreeNode root) {
        Map<TreeNode, Integer> memo = new HashMap<>();
        return robAction(root, memo);
    }

    int robAction(TreeNode root, Map<TreeNode, Integer> memo) {
        if (root == null)
            return 0;
        if (memo.containsKey(root))
            return memo.get(root);
        int money = root.val;
        if (root.left != null) {
            money += robAction(root.left.left, memo) + robAction(root.left.right, memo);
        }
        if (root.right != null) {
            money += robAction(root.right.left, memo) + robAction(root.right.right, memo);
        }
        int res = Math.max(money, robAction(root.left, memo) + robAction(root.right, memo));
        memo.put(root, res);
        return res;
    }

你可能感兴趣的:(代码随想录,算法,数据结构)