代码随想录算法训练营第四十八天 |动态规划 part9

198. 打家劫舍

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

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/house-robber
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    Integer [] dp;
    public int rob(int[] nums) {
        // dp[i] 表示从第i家屋子到最后一个屋子偷窃能得到的的最高金额
        dp = new Integer[nums.length];
        // 初始化
        // dp[0] = nums[0];
        helper(0,nums);
        return dp[0];
    }
    private int helper(int i,int[] nums){
        // System.out.println("i= "+i);
        if(i>=dp.length){
            return 0;
        }
        if(dp[i]!=null){
            return dp[i];
        }
        // 对于当前房屋i
        // 要么打劫当前房屋然后从i+2开始
        // 要么不打劫当前房屋然后从i+1开始
        dp[i] = Math.max(nums[i]+helper(i+2,nums),helper(i+1,nums));
        return dp[i];
    }
}

 213. 打家劫舍||

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/house-robber-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 环形数组考虑三种情况

1. 不包含头尾

2. 只包含头不包含尾

3. 只包含尾不包含头

情况2和3包含情况1

class Solution {
    Integer [] dp;
    public int rob(int[] nums) {
        if(nums.length==1){
            return nums[0];
        }
        // dp[i] 表示从第i家屋子到最后一个屋子偷窃能得到的的最高金额
        dp = new Integer[nums.length];
        // 包含尾不包含头
        helper(1,nums, nums.length);
        int temp = dp[1];

        dp = new Integer[nums.length];

        // 包含头不包含尾
        helper(0,nums, nums.length-1);
        int temp2 = dp[0];
        return Math.max(temp,temp2);
    }
    private int helper(int i,int[] nums, int end){
        if(i>=end){
            return 0;
        }
        if(dp[i]!=null){
            return dp[i];
        }
        // 对于当前房屋i
        // 要么打劫当前房屋然后从i+2开始
        // 要么不打劫当前房屋然后从i+1开始
        dp[i] = Math.max(nums[i]+helper(i+2,nums,end),helper(i+1,nums,end));
        return dp[i];
    }
}

337. 打家劫舍 |||

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

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

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/house-robber-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    public int rob(TreeNode root) {
        int [] res = helper(root);
        return Math.max(res[0],res[1]);
    }
    private int[] helper(TreeNode node){
        // res[0] 表示当前节点不偷
        // res[1] 表示当前节点偷
        int[] res = new int[2];
        if(node==null){
            return res;
        }
        // 后序遍历
        int[] left = helper(node.left);
        int[] right = helper(node.right);

        // 不偷当前节点, 那么考虑是否偷左右子节点
        res[0] = Math.max(left[0],left[1]) + Math.max(right[0],right[1]);
        // 偷当前节点,那么左右子节点不偷
        res[1]  = node.val + left[0]+ right[0];
        return res;
    }
}

 注意:本题一定要后序遍历,因为需要通过左右子节点返回的值来决定当前节点的值

你可能感兴趣的:(算法,动态规划,leetcode)