【题目1】

 此系列有三题,都是强盗偷家不能偷相邻邻居,否则会被发现。问最多能偷多少钱

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.

 

Example 1:

Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.

Example 2:

Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.

 

【思路】

  • 动态规划,设有1 2 3 4 5户人家
  • 要么从1要么从2开始偷(不可能从3开始偷,因为1号不偷白不偷)
  • 因此 第i家最大值=MAX((第i家的钱+ i-2家最大值),i-1家最大值)

【代码】

class Solution {
    public int rob(int[] nums) {
        int len=nums.length;
        if(len<2)
            return nums[0];
        int[] dp=new int[len];
        dp[0]=nums[0];
        dp[1]=Math.max(dp[0],nums[1]);
        for(int i=2;i<len;i++){
            dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i]);
        }
        return dp[len-1];
    }
}

 

【题目2】

 213改为首位相连的数组,即第一家不能和最后一家同时打劫,其余相同。

【思路】

  • 动态规划,分类讨论
    • 要么不打劫最后一家,可能打劫第一家
    • 要么不打劫第一家,可能打劫最后一家
  • 参考 https://www.bilibili.com/video/BV1sK411u7ZY ,去头去尾那种情况可不用讨论,已经包含其中
class Solution {
 public int rob(int[] nums) {
        int ans=0;
        if(nums.length<2)
            return nums[0];
        int[] setA= Arrays.copyOfRange(nums,1,nums.length);
        int[] setB= Arrays.copyOfRange(nums,0,nums.length-1);
        return Math.max(fun(setA),fun(setB)));
    }

//以下与题目一代码相同
public int fun(int[] nums){ if(nums.length<2) return nums.length==0?0:nums[0]; int[] dp=new int[nums.length]; dp[0]=nums[0]; dp[1]=Math.max(dp[0],nums[1]); for(int i=2;i<nums.length;i++){ dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i]); } return dp[nums.length-1]; } }

 

 

【题目】

变成了树状结构,root不能直接和左右相连

Example 1:

Input: root = [3,2,3,null,3,null,1]
Output: 7
Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.

Example 2:

Input: root = [3,4,5,1,3,null,1]
Output: 9
Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.

 

【思路】

分类讨论

1、取当前节点,不取挨着的左右节点

root.val+left[0]+right[0];

2、不取当前节点,取max左+max右节点

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

Q:为什么不直接左+右,而要max左+max右?

A:要想清楚动态规划,left[] right[]都是由fun推导出的

 

【代码】

class Solution {
    public int rob(TreeNode root) {
        int[] res=fun(root);
        return Math.max(res[0],res[1]);
    }
    
    public int[] fun(TreeNode root){
        int[] res=new int[2];
    
        if(root==null)
            return res;
        
        int[] left=fun(root.left);
        int[] right=fun(root.right);
        
       //res[0]不选当前节点,选左右 res[1]选当前节点
        res[0]=Math.max(right[0],right[1])+Math.max(left[0],left[1]);
        res[1]=root.val+left[0]+right[0];
        
        return res;
    }
}

 

 

 posted on 2021-08-22 13:10  alau  阅读(64)  评论(0编辑  收藏  举报