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

动态规划(dynamic programming)的入门题,题不难,可以在题目的原意上暴力完成,但是不会被AC。

功能好说,但是程序要考虑题目要求的时间复杂度啊。

先贴原题:

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 andit 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 tonightwithout alerting the police.

Java的实现代码是这样的( 但这段代码是暴力的,不能满足时间复杂度要求,不能被AC):

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

可以注意上方代码,每家店的选择都是2种,那么,要抢n家店,可能的方案就是2的n次方种,这样的时间复杂度就相当高了(指数级别的时间复杂度增长非常快)

如何理解呢,这个问题应该这样看:我们从后到这往前计算,当抢劫的起点是n-1或者是n-2时,二者的后续抢劫的店铺编号只有一个不一样,就是枪了n-2之后,不能抢n-3,但是抢了n-1后,可以抢n-3,之后n-1和n-2的后续抢劫店铺选择都是一样的,这样就造成了某种程度上的重复计算——一个好的算法应该是尽可能减少重复计算。

一个本质:动态规划的本质就是递归。

大牛曾经曰过:递归就是,把原问题拆解成子问题,得到子问题的答案,就得到了原问题的答案。

下面是AC后的代码(JAVA):

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

C++的ROBBER:

class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        if(n == 0)
         {   
             return 0;
         }else if(n == 1)
         {   
            return nums[0];
         } 
          else
         {
            vector<int> maxV(n, 0);
            maxV[0] = nums[0];
            maxV[1] = max(nums[0], nums[1]);
            for(int i = 2; i < n; i ++)
                maxV[i] = max(maxV[i-2]+nums[i], maxV[i-1]);
            return maxV[n-1];
        }
    }
};






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值