代码随想录打卡第五十天|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 。返回在不触动警报的情况下 ,小偷能够盗取的最高金额 。
在这里插入图片描述
在这里插入图片描述

题目链接: 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;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

没脑袋的喵

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

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

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

打赏作者

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

抵扣说明:

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

余额充值