部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

*LeetCode--198. 213. House Robber(入室强盗)

198 House Robber
问题大意:

一个强盗打算抢一条街上的若干户人家,每一家都有一定数量的财物。由于存在这样一种报警机制:如果强盗抢了两户相邻的人家,那么就会自动报警。在这种情况下,强盗怎么抢才能使得收益最大。

使用一个数组来表示每一户拥有的财物。

方法1:采用递归的方法(超时了)

第一步一定会选取nums[0]或者nums[1],即start=0或1,否则最终的结果不是最大的。
递归:对nums[start+2]之后的元素和nums[start+3]之后的元素分别进行递归,结果为nums[start]+fun(nums,start+2) 和 nums[start]+fun(nums,start+3),二者的最大值就是最大的收益。

代码:

public static int rob(int[] nums) {
    if(nums.length==0) return 0;
    System.out.println(nums.length);
    return getMaxMoney(nums,0);
}
public static int getMaxMoney(int[] nums , int start){
    int len = nums.length;
    if(start == len-1)
        return nums[len-1];
    if(start == len-2)
        return Math.max(nums[len-1],nums[len-2]);    
    int sum1 = nums[start]; 
    if(start+2<len) sum1 = nums[start] + getMaxMoney(nums,start+2);
    int sum2 = nums[start+1]; 
    if(start+3<len) sum2 = nums[start+1] + getMaxMoney(nums , start+3);
    return Math.max(sum1, sum2);
}

提交后运行超时。

 

方法2:动态规划

使用maxv[i]表示从第0个房子到第i个房子的最大收益。
对于第n个房间我们所能有的选择是偷和不偷, 那么如果是做决定是偷 则上一步必须是不偷,此时的收益是:maxv[i-2]+nums[i]
如果是不偷, 那么上一步就无所谓是不是已经偷过,此时的收益是:maxv[i-1]
递推关系:maxv[i] = Math.max(maxv[i-1], maxv[i-2]+nums[i]); 

public static int rob(int[] nums) {
    int len = nums.length;
    if(len == 0) return 0;
    if(len == 1) return nums[0];
    
    int[] maxv = new int[len];        
    maxv[0] = nums[0];
    maxv[1] = Math.max(nums[0],nums[1]);        
    for(int i = 2 ; i < len ; i++){
        maxv[i] = Math.max(maxv[i-1], maxv[i-2]+nums[i]); 
        //如果不抢第i户,那么直接用maxv[i-1],不用在意i-1户被没被抢; 如果抢这一户,则为maxv[i-2]+nums[i]
    }        
    return maxv[len-1];
}

 
213 House Robber II

对于House Robber II,基本和原来类似,只是变为首尾连接的。就是最后一户和第一户是相邻的,在这种情况下求最大收益。

方法:仍然利用动态规划,和原来的类似。
假设nums数组从0到k,那么求n到K-11到k这两者的的最大值 求法同原来的HouseRobber不相邻的情况。 

public static int rob(int[] nums) {
    int len = nums.length;
    if(len==0) return 0;
    if(len==1) return nums[0];                
    return Math.max(helper(nums,0,len-1),helper(nums,1,0));
}

public static int helper(int[] nums, int start , int end){
    int p = 0, q = 0;
    for (int i = start; i != end; /* do nothing */) {
        int tmp = p;
        p = Math.max(p, q + nums[i]);
        q = tmp;
        i = (i + 1) % nums.length;
    }
    return p;
}

 

另一种方法,对原来House Robber的改进

public static int rob(int[] nums) {
    int len = nums.length;
    if(len==0) return 0;
    if(len==1) return nums[0];
    if(len==2) return Math.max(nums[0], nums[1]);
    
            
    return Math.max(helper(nums,0,len-1),helper(nums,1,0));
}

public static int helper(int[] nums, int start , int end){
    int len = nums.length ; 
    int[] maxv = new int[len];                
    
    maxv[start] = nums[start]; //只有第一个元素情况下的最大值
    maxv[start+1] = Math.max(nums[start],nums[start+1]); //只有前两个元素情况下的最大值
    
    for(int i = (start+2+len)%len ;i != end; ){
        System.out.println(i);
        maxv[i] = Math.max(maxv[(i+len-1)%len], maxv[(i+len-2)%len]+nums[i]);
        i = (i+1)%(len);
    }
            
    return maxv[(end-1+len)%len];
}
View Code

 

 

posted @ 2015-07-20 18:24  流了个火  阅读(143)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats