动态规划:从记忆化搜索到递推 打家劫舍

目录

LeetCode198 打家劫舍

 1、递归搜索+保存计算结果=记忆化搜索

2、1:1翻译成递推

3、空间优化

LeetCode213 打家劫舍II

LeetCode198 打家劫舍

 1、递归搜索+保存计算结果=记忆化搜索

回溯三问:

(1)当前操作?枚举第i个房子选/不选

(2)子问题?从前i个房子中的得到的最大金额和

(2)下一个子问题? 分类讨论:

        不选:从前i-1个房子中得到的最大金额和

        选:从前i-2个房子中得到的最大金额和+nums[i]

记忆化搜索:把递归的计算结果保留下来,下次递归到同样的入参时,就直接返回先前保存的结果。

/*
 * @lc app=leetcode.cn id=198 lang=cpp
 *
 * [198] 打家劫舍
 */

// @lc code=start
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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

时间复杂度:O(n)

空间复杂度:O(n)

2、1:1翻译成递推

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

时间复杂度:O(n) 

空间复杂度:O(n)

3、空间优化

class Solution {
public:
    int rob(vector<int>& nums) {
        int f0=0,f1=0;
        for(int x:nums){
            int new_f=max(f1,f0+x);
            f0=f1;
            f1=new_f;
        }
        return f1;
    }
};

时间复杂度:O(n) 

空间复杂度:O(1)

LeetCode213 打家劫舍II

分类讨论,考虑是否偷 nums[0]:

如果偷 nums[0],那么 nums[1] 和 nums[n−1] 不能偷,问题变成从 nums[2] 到 nums[n−2] 的非环形版本,调用 198 题的代码解决;
如果不偷 nums[0],那么问题变成从 nums[1] 到 nums[n−1] 的非环形版本,同样调用 198 题的代码解决。

/*
 * @lc app=leetcode.cn id=213 lang=cpp
 *
 * [213] 打家劫舍 II
 */

// @lc code=start
#include <iostream>
#include <vector>
using namespace std;

class Solution {
public:
    int rob1(vector<int>& nums,int start,int end){
        int f0 = 0, f1 = 0;
        for (int i = start; i < end; i++) {
            int new_f = max(f1, f0 + nums[i]);
            f0 = f1;
            f1 = new_f;
        }
        return f1;
    } 
    int rob(vector<int>& nums) {
        int n=nums.size();
        return max(nums[0] + rob1(nums, 2, n - 1), rob1(nums, 1, n));
    }    
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值