动态规划——C++做打家劫舍Ⅰ,暴力动态解法+备忘录解法+降低空间复杂度解法

house robberⅠ

思路:

对每一个当下的房子只有两个选择:抢或者不抢,抢的话下一个判断要在当下+2的位置,不抢的话可以去面对下一间房子
状态选择,清晰明了:dp[i] = max(dp[i+2]+nums[i], dp[i])

代码,暴力动态

//关注当下,对房子就两个选择,对这个房子偷或者不偷
class Solution {
public:
    int dp(vector<int>&nums, int start)
    {
        if(nums.size() == 0)
            return 0;
        if(start >= nums.size())
            return 0;
        return max(dp(nums,start+1), dp(nums, start+2)+nums[start]);
    }
    int rob(vector<int>& nums) {
        return dp(nums, 0);
    }
};

不幸的是,超时了,ok,加个备忘录,加备忘录其实就是在复述一下上述代码再加个memo

//关注当下,对房子就两个选择,对这个房子偷或者不偷
class Solution {
public:
    int dp(vector<int>&nums, int start, vector<int>&memo)
    {
        if(memo[start] != -1) 
            return memo[start];

        if(nums.size() == 0)
            return 0;
        if(start == nums.size())
            return 0;
        if(start == nums.size()-1)
           {
             memo[start] = nums[start];
            return memo[start];
        }
        memo[start] = max(dp(nums,start+1, memo), dp(nums, start+2, memo)+nums[start]);
        return memo[start];
    }
    int rob(vector<int>& nums) {
        vector<int> memo(nums.size()+1, -1);//初始化为-1
        return dp(nums, 0, memo);
    }
};

降低空间复杂度解法

因为状态转移只与最近的两个状态有关,所以可以进一步优化,将空间复杂度降低到O(1),
先写一下dp数组的:dp[i]= x表示从第i间房开始最多能抢到x, dp[i] = max(dp[i], dp[i+2]+nums[i])

dp数组代码
class Solution {
public:
    int rob(vector<int>& nums) {//dp[i]表示从第n间房开始抢可以抢到的最大数
        int n = nums.size();
        //int dp[n+2];
        vector<int>dp(n+2, 0);
        dp[n] = 0;//base case从n开始抢, 最后一间房是n-1,所以抢个空, 找到状态,遍历状态,所以去遍历房间数
        for(int i = n-1; i>=0; i--)
        {
            dp[i] = max(dp[i+1], dp[i+2]+nums[i]);
        }
        return dp[0];//从最后开始抢,那么只要返回最后的结果就行,就是第一间房
    }
};
降低空间复杂度代码

因为当前状态只与前两个状态相关,所以只需要用变量保留前两个状态就行,不需要用dp数组将所有的状态保留下来

class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        int dp_i_1 = 0;//不抢
        int dp_i_2 = 0;//抢
        int dp_i = 0;
        for(int i= n-1; i>=0; i--)
        {
            dp_i = max(dp_i_1, dp_i_2+nums[i]);
            dp_i_2 = dp_i_1;
            dp_i_1 = dp_i;
        }
        return dp_i;//i就是当前的节点,遍历完就是最后的节点

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值