代码随想录刷题记录 day42 打家劫舍 1 2 3

代码随想录刷题记录 day42 打家劫舍 1 2 3

参考:代码随想录

198. 打家劫舍

代码随想录刷题记录 day42 打家劫舍 1 2 3_第1张图片

思想

1.dp[i]表示偷取[0,i]房间内获取的最高的金额

2.递推公式

  • 偷取第i号房间时的价值

    dp[i]=dp[i-2]+nums[i];

  • 不偷取第i号房间时的价值

    dp[i]=dp[i-1]

所以递推公式

dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i])

3.初始化

dp[0]=nums[0];

dp[1]=max(nums[0],nums[1]) ;

4.遍历顺序

从小到大

5.打印dp数组

nums=[1,2,3,1]

dp=[0,1,2,4,4]

代码

class Solution {
    public int rob(int[] nums) {
        //dp[i] 表示偷 [0,i]区间的房间能偷到的最高的金额
        //考虑以下两种情况,
        //1.偷第i间房 dp[i]=dp[i-2]+nums[i]
        //2.不偷第i间房 dp[i]=dp[i-1] 考虑i-1房
        if(nums.length==1) return nums[0];
        
        int [] dp=new int[nums.length];
        dp[0]=nums[0];
        dp[1]=Math.max(nums[0],nums[1]);
        if(nums.length==2) return dp[1];

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

        return dp[nums.length-1];
        

    }
}

213. 打家劫舍 II

代码随想录刷题记录 day42 打家劫舍 1 2 3_第2张图片

思想

考虑

偷首不偷尾

偷尾不偷首

首尾都不偷

偷首不偷尾和偷尾不偷首包括了首尾都不偷的情况

  • 将偷首不偷尾所包含的数组区间传入上一题打家劫舍的逻辑得到res1
  • 将偷尾不偷首所包含的数组区间传入上一题打家劫舍的逻辑得到res2
  • 较大的就是所求的答案

代码

class Solution {
    public int rob(int[] nums) {
        //考虑首元素  考虑尾元素
        if(nums.length==0) return 0;
        if(nums.length==1) return nums[0];

        int res1=robRange(nums,0,nums.length-2);//闭区间
        int res2=robRange(nums,1,nums.length-1);
        return Math.max(res1,res2);
    }
    public int robRange(int[] nums ,int start,int end){
        if(end==start) return nums[start];//首元素=尾元素  直接返回
        int [] dp=new int[nums.length];
        dp[start]=nums[start];
        dp[start+1]=Math.max(nums[start],nums[start+1]);
        for(int i=start+2;i<=end;i++){
            dp[i]=Math.max(dp[i-2]+nums[i],dp[i-1]);
        }

        return dp[end];
    }
}

337. 打家劫舍 III

代码随想录刷题记录 day42 打家劫舍 1 2 3_第3张图片

思想

  1. dp[0]表示不偷取当前节点获得的价值,dp[1]表示偷取当前节点获得的价值

  2. 递推公式

    • 不偷取当前节点

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

    • 偷取当前节点

      int val2=node.val+left[0]+right[0];

  3. 终止条件和初始化

    int[] dp=new int[2];

    if(node.val==null) return dp;

  4. 遍历顺序

    后序遍历

    通过递归左节点,得到左节点偷与不偷的金钱。

    通过递归右节点,得到右节点偷与不偷的金钱。

代码

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

    }
    public int[] robRecursion(TreeNode node){

        int[] dp=new int[2];
        if(node==null) return dp;
        //dp[0] 表示不偷当前节点 dp[1] 表示偷当前节点

        int[] left=robRecursion(node.left);
        int[] right=robRecursion(node.right);
        dp[0]=Math.max(left[0],left[1])+Math.max(right[0],right[1]);
        dp[1]=node.val+left[0]+right[0];

        return dp;
    }
}

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