2024年最新动态规划算法总结_动态规划函数,2024年最新C C++线程池面试题

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

进行状态转移

for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for …
dp[状态1][状态2][…] = 求最值(选择1, 选择2,…)


##### 二、解题套路


1. 明确【状态】
2. 明确【选择】
3. 明确dp函数/数组的定义
4. 明确base case


##### 三、状态压缩


如果计算状态dp[i][j]需要的都是dp[i][j]相邻的状态,那么就可以使用状态压缩技巧,将二维dp转化为以为,将空间复杂度从O(N^2)降低到O(N).


##### 四、子序列解题模板:最长回文子序列


###### 1、第一种思路是一个一维的dp数组:



int n = array.length;
int []dp = new int[n];
for(int i = 1;i<n;i++){
for(int j = 0;j<i;j++){
dp[i] = 最值(dp[i], dp[j] + …)
}
}


###### 2、第二种思路模板是一个二维dp数组



int n = arr.length;
int [][] dp = new dp[n][n];
for(int i = 0;i<n;i++){
for(int j =1;j<n;j++){
if(arr[i]==arr[j]){
dp[i][j] = dp[i][j] + …
}else{
dp[i][j] = 最值(…)
}
}
}


###### 3、涉及两个字符串/数组时(比如最长公共子序列),dp数组的含义如下:


(1) 在子数组arr[0,…i]和子数组arr2[0,…,j]中,我们要求的子序列(最长公共子序列)长度为dp[i][j]  
 (2) 只涉及一个字符串/数组时,dp数组的含义如下:  
 在子数组array[i…j]中,我们要求的子序列(最长回文子序列)的长度为dp[i][j]


###### 4、动态规划的状态转移关系


1、明确dp数组的定义。这一步对于任何动态规划问题都很重要,如果不得当或者不够清晰,会阻碍之后的步骤。  
 2、根据dp数组的定义,运用数学归纳法的思想,假设dp[0,…,i-1]都已知,想办法求出dp[i],一旦完成这一步,真个题目基本就解决了


###### 5、背包问题


(1) 明确【状态】:【背包容量】【可选择的物品】  
 (2) 明确【选择】:【装进背包】【不装进背包】  
 (3) 明确dp数组的定义:对于前i个物品,当前背包的容量为w,这种情况下可以装的最大价值是dp[i][w]  
 比如说dp[3][5] = 6, 其含义为:对于给定的一系列物品中,若只对前3个物品进行选择,当背包容量为5时,最多可装下的价值为6



int knapsack(int W, int N, vector& wt, vector& val) {
// base case 已初始化
vector<vector> dp(N + 1, vector(W + 1, 0));
for (int i = 1; i <= N; i++) {
for (int w = 1; w <= W; w++) {
if (w - wt[i-1] < 0) {
// 这种情况下只能选择不装入背包
dp[i][w] = dp[i - 1][w];
} else {
// 装入或者不装入背包,择优
dp[i][w] = max(dp[i - 1][w - wt[i-1]] + val[i-1],
dp[i - 1][w]);
}
}
}

return dp[N][W];

}


###### 6、股票问题



> 
> 动态规划算法本质上就是穷举【状态】,然后再【选择】上选择最优解
> 
> 
> 


(1)穷举状态:天数i,允许交易的最大次数k,当前的持有状态0 or 1。  
 (2)穷举选择: 买入,卖出,无操作



dp[i][k][0 or 1]
0 <= i <= n-1, 1 <= k <= K
// n为天数,大K为交易数的上限,0 和 1代表是否持有股票
// 此问题共n*K*2种状态,全部穷举就可搞定

for 0 <= i < n:
for 1 <= k <=K:
for s in {0,1}:
dp[i][k][s] = max(buy, sell, rest)


(3) 状态转移方程  
 dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])  
 max(今天选择rest, 今天选择sell)  
 解释: 今天我没有持有股票,有两种可能,我从这两种可能中求最大利润


1. 我昨天就没有持有,且截至昨天最大交易次数限制为k,然后我今天选择rest,所以我今天还是没有持有,最大交易次数限制依然为k  
 2、 我昨天持有股票,且截至昨天最大交易次数限制为k; 但是今天我sell了,所以我今天没有持有股票了,最大交易次数限制依然为k


dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])  


![img](https://img-blog.csdnimg.cn/img_convert/f55127f31a16a0db00c913cd9ba6c4ec.png)
![img](https://img-blog.csdnimg.cn/img_convert/396f6c73d92e6ee790bd830e0de60399.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值