动态规划经典题目_「动态规划经典算法」本周总结(二)

通知:我已经将刷题指南全部整理到了Github :https://github.com/youngyangyang04/leetcode-master,方便大家在电脑上阅读,这个仓库每天都会更新,大家快去给一个star支持一下吧!

周一

「力扣」动态规划经典面试题:不同路径 中求从出发点到终点有几种路径,只能向下或者向右移动一步。

我们提供了三种方法,但重点讲解的还是动规,也是需要重点掌握的。

dp[i][j]定义 :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径

本题在初始化的时候需要点思考了,即:

dp[i][0]一定都是1,因为从(0, 0)的位置到(i, 0)的路径只有一条,那么dp[0][j]也同理。

所以初始化为:

for (int i = 0; i 

这里已经不像之前做过的题目,随便赋个0就行的。

遍历顺序以及递推公式:

for (int i = 1; i 
9b372c893a6e3b48abe58f7cab7470eb.png

周二

「leetcode」动态规划经典面试题:不同路径,有障碍 相对于动态规划:不同路径添加了障碍。

dp[i][j]定义依然是:表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

本题难点在于初始化,如果(i, 0) 这条边有了障碍之后,障碍之后(包括障碍)都是走不到的位置了,所以障碍之后的dp[i][0]应该还是初始值0。

如图:

5baeaebdb33ff63ee4f70fd41a543255.png

这里难住了不少同学,代码如下:

vector> dp(m, vector(n, 0));for (int i = 0; i 

递推公式只要考虑一下障碍,就不赋值了就可以了,如下:

for (int i = 1; i 

拿示例1来举例如题:

adf11ca55ce89738a3ac6189b585b23b.png

对应的dp table 如图:

2745b5cec4a13b8fb873df0d5c99ec0e.png

周三

「力扣」动态规划经典面试题:整数拆分,你要怎么拆? 给出一个整数,问有多少种拆分的方法。

这道题目就有点难度了,题目中dp我也给出了两种方法,但通过两种方法的比较可以看出,对dp数组定义的理解,以及dp数组初始化的重要性。

dp[i]定义:分拆数字i,可以得到的最大乘积为dp[i]

本题中dp[i]的初始化其实也很有考究,严格从dp[i]的定义来说,dp[0] dp[1] 就不应该初始化,也就是没有意义的数值。

拆分0和拆分1的最大乘积是多少?

这是无解的。

所以题解里我只初始化dp[2] = 1,从dp[i]的定义来说,拆分数字2,得到的最大乘积是1,这个没有任何异议!

vector dp(n + 1);dp[2] = 1;

遍历顺序以及递推公式:

for (int i = 3; i <= n ; i++) {    for (int j = 1; j 

举例当n为10 的时候,dp数组里的数值,如下:

e80cc50dead2ff6c90908d3f4f2ca61c.png

一些录友可能对为什么没有拆分j没有想清楚。

其实可以模拟一下哈,拆分j的情况,在遍历j的过程中dp[i - j]其实都计算过了。

例如 i= 10,j = 5,i-j = 5,如果把j拆分为 2 和 3,其实在j = 2 的时候,i-j= 8 ,拆分i-j的时候就可以拆出来一个3了。

或者也可以理解j是拆分i的第一个整数

动态规划:整数拆分,你要怎么拆?总结里,我也给出了递推公式dp[i] = max(dp[i], dp[i - j] * dp[j])这种写法。

对于这种写法,一位录友总结的很好,意思就是:如果递推公式是dp[i-j] * dp[j],这样就相当于强制把一个数至少拆分成四份。

dp[i-j]至少是两个数的乘积,dp[j]又至少是两个数的乘积,但其实3以下的数,数的本身比任何它的拆分乘积都要大了,所以文章中初始化的时候才要特殊处理。

周四

我用动态规划,就能找出有多少个不同的二叉搜索树

这道题目还是比较难的,想到用动态规划的方法就很不容易了!

dp[i]定义 :1到i为节点组成的二叉搜索树的个数为dp[i]

递推公式:dp[i] += dp[j - 1] * dp[i - j]; ,j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量

dp数组如何初始化:只需要初始化dp[0]就可以了,推导的基础,都是dp[0]。

n为5时候的dp数组状态如图:

22a951a6f9adc842618cd6fb9388e164.png

总结

本周题目已经开始点难度了,特别是动态规划:不同的二叉搜索树这道题目,明显感觉阅读量很低,可能是因为确实有点难吧。

我现在也陷入了纠结,题目一简单,就会有录友和我反馈说题目太简单了,题目一难,阅读量就特别低。

我也好难那,哈哈哈。

但我还会坚持规划好的路线,难度循序渐进,并以面试经典题目为准,该简单的时候就是简单,同时也不会因为阅读量低就放弃有难度的题目!

录友们看到这是不是得给个Carl点个赞啊[让我看看]。

预告,我们下周正式开始讲解背包问题,经典的不能再经典,也是比较难的一类动态规划的题目了,录友们上车抓稳咯。

我是程序员Carl,个人主页:https://github.com/youngyangyang04

这里每天8:35准时推送一道经典算法题目,我选择的每道题目都不是孤立的,而是由浅入深,环环相扣,帮你梳理算法知识脉络,轻松学算法!

@代码随想录 期待你的关注

我花了半年时间,整理的力扣刷题攻略,已经全部发布在Github上,点击下方链接查看吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值