leetcode198

leetcode 198 House Robber

两种方式思考状态转移方程:

  1. robberedMoney [i]=max(robberedMoney[i-k]){ 其中2<=k<=i}+nums[i]; // 以下简写为rM
    解释:当抢劫 前i个房子时,最大钱数为抢0个到前i-2个的最大值加上抢劫当前房子的钱。
    比如[2,1,1,2 ,3] ;
    抢第1个房子时,最大钱数0+2;rM=[2];
    抢第2个房子时,最大钱数为0+1;rM=[2,1];// 前两个是base case
    抢前3个房子时,最大钱数为max([2])+1;rM=[2,1,3];
    抢前4个房子时,最大钱数为max([2,1])+2=4; rM=[2,1,3,4];
    抢前5个房子时,最大钱数为Max([2,1,3])+3=6; rM=[2,1,3,4,6];
    这种方式思考最容易想到但想要时间复杂度为O(n),必须再开一个数组维护前i-2个rM的最大值 空间不够优化
class Solution {
public:
    int rob(vector<int>& nums) {
        // 状态转移方程 dp[i]=max(dp[i-k]){2<=k<=i}+nums[i];
        int n=nums.size();
        if(n==0){
            return 0;
        }
        if(n==1){
            return nums[0];
        }
        vector<int> rM(n),maxbefore(n);
        dp[0]=nums[0],dp[1]=nums[1];
        maxbefore[0]=nums[0];
        maxbefore[1]=max(nums[0],nums[1]);
        for(int i=2;i<n;++i){
            rM[i]=maxbefore[i-2]+nums[i];
            maxbefore[i]=max(rM[i-1],rM[i]);
        }
        return maxbefore[n-1];
    }
};
  1. rM[i]=max(rM[i-2]+nums[i],rM[i-1]);
    解释:对与第i个房子,有两种选择(a)抢,(b)不抢
    如果选a,接下来就只能抢劫前i-2个房子 钱数为让rM[i-2]+nums[i];
    如果选b,抢劫前i-1个房子 钱数为rM[i-1];
    选其中的较大者即为所得
    这种写法rM为第一种的maxbefore;所以可以看到第一种没有第二种好
    这里给出带memo(rM)的写法 自底向上的写法直接修改上一个就好了
    一直都觉得带memo的更好理解
    代码来自leetcode198-Discuss-heroes3001
int[] memo;
public int rob(int[] nums) {
    memo = new int[nums.length + 1];
    Arrays.fill(memo, -1);
    return rob(nums, nums.length - 1);
}

private int rob(int[] nums, int i) {
    if (i < 0) {
        return 0;
    }
    if (memo[i] >= 0) {
        return memo[i];
    }
    int result = Math.max(rob(nums, i - 2) + nums[i], rob(nums, i - 1));
    memo[i] = result;
    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值