LeetCode-198:打家抢劫

题目描述:
你是一个专业的强盗,计划抢劫沿街的房屋。每间房都藏有一定的现金,阻止你抢劫他们的唯一的制约因素就是相邻的房屋有保安系统连接,如果两间相邻的房屋在同一晚上被闯入,它会自动联系警方。

给定一个代表每个房屋的金额的非负整数列表,确定你可以在没有提醒警方的情况下抢劫的最高金额。

方法一、 暴力搜索:
思路:文中给出不能连续抢两家,因此假设从最后一个房屋开始抢,最后一个房屋为idx。将原问题分割成子问题,子问题的最优决策可以导出原问题的最优决策。现有两种可能情况,当前房屋抢和当前房屋不抢。若当前房屋抢,则下一房屋不能抢;若当前房屋不抢,则下一房屋可抢;选出这两种情况的最大值,递归执行,直到idx<0。

class Solution {
    public int solve(int idx,int[] nums){
        if(idx<0){
                return 0;
        }         
        return Math.max(nums[idx]+solve(idx-2,nums),solve(idx-1,nums));
    }
    public int rob(int[] nums) {

        return solve(nums.length-1,nums);
    }
}

方法二、动态规划
在递归方法中,存在大量的重复计算问题:
假如抢第n-1家,就得计算n-3,n-4,n-5,…
n-1 -> (n-3,n-4,n-5,…)
假如抢第n-2家,就得计算n-3,n-4,…
n-2 -> (n-4,n-5,…)
因此,每一家都有两种可能可能,抢或者不抢。则该算法的时间复杂度为:O(2n)。这样就重复计算了很多,我们应该找到方法避免重复计算,每个值的计算应该保存下来,当下次被需要直接拿来用。这就是去冗余,用采用空间换时间的方法。因此当n-1房屋的最优解算过后,就能推导出n房屋的最优解。这就是动态规划的思想。(两点:最优子结构、去冗余)

动态规划:

  • 本质是递归。原问题(N)->子问题(N-1)->原问题(N)
  • 最优子结构
    子问题最优决策可导出原问题最优决策
    无后效性——当前的决策不影响后面的决策
    自顶向下:先算最大的值,再往下进行。缺点:处理边界较多。
class Solution {
    public static int[] result;
    public int solve(int idx,int[] nums){

        if(idx<0){
                return 0;
        }        
        if(result[idx]>=0){
            return result[idx];
        }
        result[idx] = Math.max(nums[idx]+solve(idx-2,nums),solve(idx-1,nums));
        return result[idx];
    }
    public int rob(int[] nums) {
        result = new int[nums.length];
        for(int i=0;i<nums.length;++i){
            result[i] = -1;
        }

        return solve(nums.length-1,nums);
    }
}

自底向上:

class Solution {     
    public int rob(int[] nums) {
        int[] result;
        if(nums.length==0)
            return 0;       
        result=new int[nums.length];
        result[0]=nums[0];
        result[1]=Math.max(nums[0],nums[1]);        
        for (int idx=2;idx<nums.length;++idx){
            result[idx] = Math.max(nums[idx]+result[idx-2],result[idx-1]);
        }        
        return result[nums.length-1];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值