Leetcode 198. House Robber & 213. House Robber II & 337. House Robber III

原创 2016年05月30日 11:50:28

198. House Robber

Total Accepted: 71597 Total Submissions: 206073 Difficulty: Easy

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.


必然是用DP。所有叙述当前房屋=今天,前一个房屋等于昨天,以此类推。


一开始觉得,今天到底来自前天还是昨天,昨天用没用 value,我怎么知道,于是建立了俩数组,自然是AC。

public class Solution {
    public int rob(int[] nums) {
        if(nums==null || nums.length==0) return 0;
        if(nums.length==1) return nums[0];
        if(nums.length==2) return nums[1]>nums[0] ? nums[1] : nums[0];
        
        int[] res = new int[nums.length];
        boolean[] flag = new boolean[nums.length];
        // 初始化
        res[0]=nums[0]; flag[0]=true;
        if(nums[1]>nums[0]){
            res[1]=nums[1]; flag[1]=true;
        }else{
            res[1]=nums[0]; flag[1]=false;
        }
        // 初始化完
        for(int i=2; i<res.length; i++){
            if(flag[i-1]==true){
                int temp=res[i-2]+nums[i];
                if(temp>res[i-1]){
                    flag[i]=true;
                    res[i]=temp;
                }else{
                    flag[i]=false;
                    res[i]=res[i-1];
                }
            }else{
                res[i]=res[i-1]+nums[i];
                flag[i]=true;
            }
        }
        return res[res.length-1];
    }
}

然而网上的版本如下:

public class Solution {
    public int rob(int[] num) {
        if (num==null || num.length==0) return 0;
        int maxToPos[] = new int[num.length+1]; //the maximum amount to the i'th house 
        maxToPos[0] = 0;
        maxToPos[1] = num[0];
        for (int i=2; i<maxToPos.length; i++){
			maxToPos[i] = Math.max(maxToPos[i-1],maxToPos[i-2]+num[i-1]);
        }
        return maxToPos[maxToPos.length-1];
    }
}

简单明了。于是想了一阵子怎么回事。首先如果是当前元素和前天结果,没问题, 不可能相邻;如果只取昨天的结果,不要今天元素,没问题,不冲突。问题是:如果昨天的结果其实没用昨天的元素,那么今天就可以加今天的元素了,那么不就漏掉一种CASE? 从AC的结果来看,肯定是没有漏。为什么?


比如就4天。1,2,3,4。今天是4,那么今天的结果有可能来自结果2+元素4或者结果3。有没有可能3结果中没用3呢?3的结果是1结果+元素3和2结果中的最大值。首先,1和2一定是满足不连续的规则,因为是头两天。那么如果3的结果不包含元素3,3只能来自结果2。如果没懂,换句话说,当结果3中不包含元素3的时候,那么结果3和结果2是一样的!所以对于结果4的判断,没有漏掉任何CASE。


213. House Robber II

Total Accepted: 29523 Total Submissions: 95288 Difficulty: Medium

Note: This is an extension of House Robber.

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.


思路:

聪明的人真多,自己比较笨。想的是,用个flag表示用没用第一个元素,然后在末尾判断。首先是代码非常的繁琐,然后对于[1,1,1,2]这个例子,走到第三个1,都判定0位置元素使用了,然而结果出自不用该0元素。

聪明的解法是,我也不管你用了没用,判断那么多CASE多累。我就走两遍,把你俩分开。一遍有首元素,这样没有末尾元素,长度是length-1;一边是没有首元素,有末尾元素,长度是length-1。

public class Solution {
    public int rob(int[] num) {
        if (num==null || num.length==0) return 0;
        if (num.length==1) return num[0];
        int maxToPos[] = new int[num.length];
        int max1 = 0;
        maxToPos[0] = 0;
        maxToPos[1] = num[0];
        for (int i=2; i<=maxToPos.length-1; i++){
			maxToPos[i] = Math.max(maxToPos[i-1],maxToPos[i-2]+num[i-1]); // 0, 1, 2 <-> dp 1 2 3
        }
        max1= maxToPos[num.length-1];
        
        maxToPos[1] = num[1];
        for (int i=2; i<=maxToPos.length-1; i++){
			maxToPos[i] = Math.max(maxToPos[i-1],maxToPos[i-2]+num[i]); // 1, 2, 3 <-> dp 1 2 3
        }
        return Math.max(max1, maxToPos[num.length-1]);
    }
}


337. House Robber III

Total Accepted: 12749 Total Submissions: 34058 Difficulty: Medium

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.


这题其实挺难的,想了半天都不会。


一开始以为将每个level的点遍历,存到数组同一个level的位置,这样问题就变成了House Robber I。然而 error告诉我只是要求节点不相邻。这就麻烦了。


然而高手就是高手,总是有nice, clean的解。参考这里。最初的思维是说,我要传递max,那我怎么知道子节点使用了没使用子节点的值?高手说:好说,那就传递俩值(int[]),一个代表加上该节点的max值,另外一个代表不要该节点的max值。前者由该点的值+俩子节点不算值得出;后者则由俩子节点各自max之和得出(当前节点不用,所以对子节点是否使用不限制)。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public int rob(TreeNode root) {
        int[] num = dfs(root);
        return Math.max(num[0], num[1]);
    }
    private int[] dfs(TreeNode x) {
        if (x == null) return new int[2];
        int[] left = dfs(x.left);
        int[] right = dfs(x.right);
        int[] res = new int[2];
        res[0] = left[1] + right[1] + x.val;
        res[1] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
        return res;
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

算法分析与设计——LeetCode:198. House Robber

题目 You are a professional robber planning to rob houses along a street. Each house has a certai...
  • sysu_CN
  • sysu_CN
  • 2018年01月03日 16:34
  • 35

关于LeetCode中House Robber一题的理解

题目如下: You are a professional robber planning to rob houses along a street. Each house has a cer...
  • zsy112371
  • zsy112371
  • 2016年09月14日 23:03
  • 169

House Robber(窃贼的计划)

You are a professional robber planning to rob houses along a street. Each house has a certain amount...
  • ajiangfan
  • ajiangfan
  • 2016年11月10日 21:08
  • 121

House Robber【打家劫舍】【容易】

一、题目 英文:House Robber 中文:打家劫舍 二、内容要求 英文:You are a professional robber planning to rob houses al...
  • hitscutee
  • hitscutee
  • 2017年07月28日 11:58
  • 75

动态规划解决leetcode中的House Robber问题

House Robber,leetcode, 动态规划
  • PinkFriday
  • PinkFriday
  • 2017年12月09日 09:56
  • 82

LeetCode之DP(动态规划)之House Robber

动态规划(dynamic programming)的入门题,题不难,可以在题目的原意上暴力完成,但是不会被AC。 功能好说,但是程序要考虑题目要求的时间复杂度啊。 先贴原题: You are a p...
  • icehui2012
  • icehui2012
  • 2017年01月29日 23:22
  • 59

每周LeetCode算法题(七): 题目: 198. House Robber

每周LeetCode算法题(七)题目: 198. House Robber You are a professional robber planning to rob houses along a...
  • JacKnights
  • JacKnights
  • 2017年10月19日 12:42
  • 80

算法题——House Robber(JAVA)

一个数组,不能取连续的两个值,求可得到和的最大值。
  • ivyusing
  • ivyusing
  • 2017年04月09日 22:41
  • 71

[leetcode]解决House Robber的一点小心得

本次选择的题目是 You are a professional robber planning to rob houses along a street. Each house has a ...
  • qq_38121300
  • qq_38121300
  • 2017年12月10日 13:02
  • 26

House Robber 动态规划的使用

题目链接:https://leetcode.com/problems/house-robber/ 简单归纳题目为:给定一组非负整数数组num,从中找值最大的子序列,要求子序列中任意两个元素在原数组中都...
  • jianjian1992
  • jianjian1992
  • 2015年04月09日 09:31
  • 413
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Leetcode 198. House Robber & 213. House Robber II & 337. House Robber III
举报原因:
原因补充:

(最多只允许输入30个字)