198. House Robber

一、题意
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.
二、分析和解答

    public int rob(int[] nums) {
        int s1 = 0;//not rob
        int s2 = 0;//rob
        for(int i=0;i<nums.length;i++){
            //tmp保存不抢上一家的值
            int tmp =  s1;
            //不抢这一家,等于  抢上一家和不抢上一家的较大值
            s1 = Math.max(s1,s2);//not rob
            //抢这一家, 等于 不抢上一家 和 这一家的和
            s2 = tmp + nums[i];
        }   
        return Math.max(s1,s2);
    }

不能抢劫连着的两家。更通俗一点:求数组中不连续数字的最大的和。
这里假设S[i]是抢劫到第i家的时候钱的总数,那么
S[i] = nums[i] + S[i-2] (抢第i家家) 或者是S[i] = S[i-1](不抢第i家)

  int search(int id,int[] nums,int[] sum){
        if(id < 0)
            return 0;
        return Math.max(nums[id] + search(id-2,nums),search(id-1,nums));
    }
    public int rob(int[] nums) {
        return search(nums.length-1,nums);
    }

提交后发现,时间超时!从代码可以看到,每一个递归里面有两个子递归,最后导致整个函数的时间复杂度达到了2^n左右。
2、优化
冗余的部分在于:之前已经记录过的数据没有被利用,所以这里申请一个数组来记录之前运算过的数据!

  public 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]);

        int[] sum = new int[nums.length];

        sum[0] = nums[0];
        sum[1] = Math.max(nums[0],nums[1]);
        //sum[2] = Math.max(nums[0] + nums[2],nums[1]);

        int i = 2;//3;
        while(i < len){
            sum[i] = Math.max(sum[i-1],nums[i] + sum[i-2]);
            i++;
        }
        return sum[i-1];
    }

3、再优化
后来发现,我们只需要最后的sum[i]这一个数据,因此是没有必要申请一个数组,仅仅需要两个变量即可,一个记录不抢当前这家所获得的总利润(其实就是抢劫上一家和不抢劫上一家利润的最大值,因为如此,这家得到的利润就是0,还是上一家的数据,但肯定是较大者),另一个记录抢劫这家所获得的总利润(从上一家得到的最大值加上这家的数据)。

    public int rob(int[] nums) {
        int s1 = 0;//not rob
        int s2 = 0;//rob
        for(int i=0;i<nums.length;i++){
            int tmp =  s1;
            s1 = Math.max(s1,s2);//not rob
            s2 = tmp + nums[i];
        }   
        return Math.max(s1,s2);
    }

Note:抢劫上一家(前一家不能rob)不一定会比 不抢劫上一家(前一家可以rob)的值大,因为前一家有影响啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值