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 OJ> (198 / 213) House Robber(I / II)

House Robber My Submissions Question Total Accepted: 45702 Total Submissions: 142460 Difficulty:...

leetcode - 198,213. House Robber(II) & 91. Decode Ways

算法系列博客之Dynamic Programming 本篇博客将运用动态规划的思想来解决leetcode上198和213号问题 问题描述:198 House RobberYou are a pr...

198/213/337 House Robber

198 House Robber You are a professional robber planning to rob houses along a street. Each house ha...

LeetCode-198&213.House Robber

https://leetcode.com/problems/house-robber/ You are a professional robber planning to rob houses...

leetcode 198 & 213:House Robber

一.House Robber I 的题意是:有一排商铺,强盗不能连续抢劫相邻的两家,否则会触动报警器,求强盗在不触动报警器的前提下,可以抢劫的最多金钱总和。(输入一维数组,从中选择若干个数,使得这些数...

LeetCode #337 - House Robber III - Medium

ProblemThe thief has found himself a new place for his thievery again. There is only one entrance to...

[leetcode]337. House Robber III

The thief has found himself a new place for his thievery again. There is only one entrance to this a...

LeetCode 337. House Robber III

大概题意:给定一棵二叉树,每个节点都有一个值,要求从其中选取若干个节点,是的值的和最大,约束条件为任意两个选取的节点之间不能相连。           解题的思路也很清晰,我们可以用动态规划的做法,...

leetcode 337:House Robber III

leetcode 337:House Robber III。leetcode新题,递归的动态规划

leetcode_middle_31_337. House Robber III

分析: 找出二叉树中最大的不相邻结点的值的和 题意: 一开始的想法是用一个布尔型参数确定下一个结点的值取不取,想的是就两种情况,一层取,下一层就不去...: private void h...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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