Day42 | 动态规划 :选或不选 打家劫舍&&打家劫舍II

Day42 | 动态规划 :选或不选 打家劫舍&&打家劫舍II

动态规划应该如何学习?-CSDN博客

动态规划学习:

1.思考回溯法(深度优先遍历)怎么写

注意要画树形结构图

2.转成记忆化搜索

看哪些地方是重复计算的,怎么用记忆化搜索给顶替掉这些重复计算

3.把记忆化搜索翻译成动态规划

基本就是1:1转换

文章目录

198.打家劫舍

[198. 打家劫舍 - 力扣(LeetCode)](https://leetcode.cn/problems/house-robber/description/)\](https://leetcode.cn/problems/integer-break/description/) #### 思路分析: **树形结构图** ![image-20241110122753429](https://img-blog.csdnimg.cn/img_convert/88ea21890f32bcbb8fc1471752135a64.png) 先明确一下dp数组/dfs函数的含义,dp\[i\]就是在前i个房子里面打家劫舍,能得到的最高金额(就是题目要求的) 我们从最后一个房子倒着往前分析子问题 对于一个房子i,我们只有两种方案,选或者不选 选了的话,那我i-1就不能选了 不选的话,那我前i个房子可以得到的最大金额数量就和前i-1个房子可以得到的最大金额数量相等,因为第i个房子没选 所以可以很轻易的得出 ```cpp dp[i]=max(dp[i-1],dp[i-2]+nums[i]); ``` **即在可能的两种方案中挑选一个最大值** #### 1.回溯 DFS **1.返回值和参数** i是房子编号 nums是房子数字 dfs返回值就是前i个房子里面打家劫舍可以得到的最大金额(和dp数组含义相同) ```cpp int dfs(int i,vector& nums) ``` **2.终止条件** 可以看到我们递归到0就是叶子结点了,下标0是第一个房子,所以小于0就代表没有房子可以选了,没有房子可以选也就没有金额,就返回0 ```cpp if(i<0) return 0; ``` **3.本层逻辑** 如上所说,返回两者的最大值给上层递归函数就好 ```cpp return max(dfs(i-1,nums),dfs(i-2,nums)+nums[i]); ``` **完整代码:** 当然,这是超时的 ```cpp class Solution { public: int dfs(int i,vector& nums) { if(i<0) return 0; return max(dfs(i-1,nums),dfs(i-2,nums)+nums[i]); } int rob(vector& nums) { return dfs(nums.size()-1,nums); } }; ``` #### 2.记忆化搜索 就是搞一个哈希表dp,全都初始化为-1,每次返回前给哈希表dp赋值,碰到不是-1的那就是算过的,那就直接返回计算过的结果,不需要再次递归了 ```cpp class Solution { public: int dfs(int i,vector& nums,vector& dp) { if(i<0) return 0; if(dp[i]!=-1) return dp[i]; return dp[i]=max(dfs(i-1,nums,dp),dfs(i-2,nums,dp)+nums[i]); } int rob(vector& nums) { vector dp(nums.size(),-1); return dfs(nums.size()-1,nums,dp); } }; ``` #### 3.1:1翻译为动态规划 **1.确定dp数组以及下标的含义** dp数组就是前i个房子里面可以取得的最大金额 下标就是房子编号 **2.确定递推公式** 忘记了原因的请看思路分析部分 ```cpp dp[i]=max(dp[i-1],dp[i-2]+nums[i]); ``` **3.dp数组如何初始化** **第一种写法**,dp数组的下标从0开始,在i=0和i=1我们的递推公式中会有不合法的状态,所以i需要从2开始 那么dp\[0\]和dp\[1\]就需要初始化,那么初始化为多少呢? 如果可以根据dp的含义想通如何初始化是最好的,比如前1间房子最大值就是nums\[0\],前两间房子最大值就是max(nums\[0\],nums\[1\]) 如果想不通的话,回到回溯法把0和1带进去就完事得出结果就完事 ```cpp class Solution { public: int dfs(int i,vector& nums) { if(i<0) return 0; return max(dfs(i-1,nums),dfs(i-2,nums)+nums[i]); } int rob(vector& nums) { return dfs(nums.size()-1,nums); } }; ``` 会得到如下的初始化方案: ```cpp vector dp(nums.size(),0); dp[0]=nums[0]; if(nums.size()>1) dp[1]=max(nums[0],nums[1]); else return dp[0]; ``` **第二种写法** dp数组的下标全部都+2(注意nums数组的下标是没变的,此时dp数组的2对应的是nums的0) 这样就避免了下标是负数的情况,完美贴合了dfs回溯的方法 ```cpp vector dp(nums.size()+2,0); for(int i=0;i& nums) { vector dp(nums.size(),0); dp[0]=nums[0]; if(nums.size()>1) dp[1]=max(nums[0],nums[1]); else return dp[0]; for(int i=2;i& nums) { vector dp(nums.size()+2,0); for(int i=0;i nums) { vector dp(nums.size()+2,0); for(int i=0;i& nums) { if(nums.size()==1) return nums[0]; if(nums.size()==2) return max(nums[0],nums[1]); return max( nums[0]+rob1(vector(nums.begin()+2,nums.end()-1)), rob1(vector(nums.begin()+1,nums.end()))); } }; ```

相关推荐
超自然祈祷16 分钟前
数据结构入门:图的基本操作、算法与 C++ 实现
算法·图搜索算法
蒙奇D索大22 分钟前
【数据结构】排序算法精讲 | 快速排序全解:高效实现、性能评估、实战剖析
数据结构·笔记·学习·考研·算法·排序算法·改行学it
程序员良辰23 分钟前
【算法新手入门】基本数据类型
算法
Blossom.11826 分钟前
基于混合检索架构的RAG系统优化实践:从Baseline到生产级部署
人工智能·python·算法·chatgpt·ai作画·架构·自动化
断剑zou天涯28 分钟前
【算法笔记】有序表——AVL树
笔记·算法
巧克力味的桃子29 分钟前
算法:大数除法
算法
@小码农30 分钟前
2025年12月 GESP认证 图形化编程 一级真题试卷(附答案)
开发语言·数据结构·算法
巧克力味的桃子31 分钟前
让程序在读取到整数0时就终止循环
c语言·算法
_OP_CHEN33 分钟前
【算法基础篇】(三十九)数论之从质数判定到高效筛法:质数相关核心技能全解析
c++·算法·蓝桥杯·埃氏筛法·acm/icpc·筛质数·欧拉筛法
算法与编程之美36 分钟前
损失函数与分类精度的关系
人工智能·算法·机器学习·分类·数据挖掘