【leetcode】198.HouseRobber

198.HouseRobber

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 system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

Tips:你是一名职业抢劫犯,计划在街上抢劫房屋。每个房子都有一定数量的钱,唯一能阻止你抢劫的限制就是相邻的房子有相连的安全系统,当相邻的两个房子在同一晚被抢劫,就会自动报警。给定一组非负整数,表示每个房子的钱数,确定你今晚可以抢劫的最大金额,而不用报警。

输入:int[] 表示每个房子内的钱数。

输出:能抢劫的最大钱数。

只要比较当前值,与前一个值加上nums[]之和的大小即可。

package easy;

public class L198HouseRobber {

    public int rob(int[] nums) {
        int pre = 0;
        int cur=0;
        int len = nums.length;
        if (nums == null || len == 0)
            return 0;
        for(int i=0;i<len;i++){
            int temp=Math.max(pre+nums[i], cur);
            pre=cur;
            cur=temp;
        }
        return cur;
    }

    public static void main(String[] args) {
        int[] nums = { 2, 1, 1, 2 ,1,1};
        int[] nums1 = { 1, 2, 3, 4, 5, 6, 7, 8 };
        int[] nums2={2,7,9,3,1};
        L198HouseRobber l98 = new L198HouseRobber();
        int money = l98.rob(nums2);
        System.out.println(money);
    }
}

 动态规划的方法,维护一个数组dp,dp[i]表示到i位置时不相邻数能形成的最大和。

public int rob(int[] nums) {
        if(nums.length<=0) return 0;
        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]);
        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];
    }

213. House Robber II

Question:After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

Tips:小偷换了一个地方接着偷,这次所有的房子围成一个圈。怎么偷钱最多,而不惊动警察。

思路:由于上一个题目房子在一条直线上,现在的房子是在一个圆环内,我们可以想办法将圆环拆成直线。第一步首先决定是否偷第一个房子。可以将问题拆分为两种情况,(0~nums.length-1)与(1~nums.length-2).拆分之后就又变会第一个问题。

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

 337. House Robber III

Question:The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.

Determine the maximum amount of money the thief can rob tonight without alerting the police.

Example 1:

     3
    / \
   2   3
    \   \ 
     3   1

Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.

Example 2:

     3
    / \
   4   5
  / \   \ 
 1   3   1

Maximum amount of money the thief can rob = 4 + 5 = 9.

Tips:小偷又换一个地方接着偷。此地房子只有一个入口叫root,每个房子有且只有一个父房子。求可偷最大金额。

思路:这个题给我的第一感觉就是需要按层得出财富最大值,分为两种情况:

(1)包含root结点,以及之后的第三层结点

(2)不包含root结点,从第二层开始隔层相加。

代码:

  public int rob(TreeNode root) {
        if(root==null)return 0;
        int ans=0;
        if(root.left!=null){
            ans+=rob(root.left.left)+rob(root.left.right);
        }
        if(root.right!=null){
            ans+=rob(root.right.left)+rob(root.right.right);
        }
        return Math.max(ans+root.val,rob(root.left)+rob(root.right));
    }

但是这种方法存在重复计算非常多。所以我们可以通过保存计算结果来减少计算量。(使用hashmap存储中间结果。)

 

 public int rob(TreeNode root){
        if(root==null)return 0;
        HashMap<TreeNode,Integer> map= new HashMap<>();
        return rob(root,map);
    }
    public int rob(TreeNode root,HashMap map) {
        if(root==null)return 0;
        int ans=0;
        if(map.containsKey(root)){
             return (int)map.get(root);
         }
        if(root.left!=null){
            ans+=rob(root.left.left,map)+rob(root.left.right,map);
        }
        if(root.right!=null){
            ans+=rob(root.right.left,map)+rob(root.right.right,map);
        }
        ans=Math.max(ans+root.val,rob(root.left,map)+rob(root.right,map));
        map.put(root,ans);
        return ans;
    }

 

posted @ 2018-01-31 13:52  于淼  阅读(181)  评论(0编辑  收藏  举报