一,介绍
1,动态规划在数学,计算机科学和经济学等领域中极为常见,是一种通过把原问题分解为相对简单的子问题的方式来求解的方法。
2,动态规划是近几年科技公司面试的必考算法,题目类型多,没有固定模板,难度大多属于中上,根据面试统计结果,一般失败的面试都与动态规划有关。但是动态分析并不可怕,可怕的是你的内心,不要遇到这种题就绕道而行。其实是有规律可行的,我们下面来通过几个经典例子,掌握其中的思想,举一反三!
eg1:
你有三种硬币,分别面值2元,5元和7元,每种硬币都有足够多。买一本书需要27元,如何用最少的硬币组合正好还清,不需要对方找钱。
(1)按照常理,最少的硬币组合 即尽量用面值大的硬币
- 7+7+7=21
- 21+5=26
- 呃。。。
(2) 改算法:尽量用大的硬币,最后如果可以用一种硬币付清就行。
- 7+7+7=21
- 21+2+2+2=27
- 6枚硬币,应该对了吧。。。
正确答案是 7+5+5+5+5=27
5枚硬币
不可思议吧,哈哈哈,别吃惊,我来告诉你为什么** _ **
动态规划组成部分一:确定状态
(1)状态太动态规划中作用属于定海神针( important!)
(2)简单地说,解动态规划的时候,需要开一个数组,数组的每一个元素构成的 f[i][j] 表示什么
类似于数学题中,x,y,z代表什么
(3)确定状态需要两个意识:
<1>最后一步
<2>子问题
<1>“最后一步”
虽然我们也不知道最优策略是什么,但是最优策略肯定是K枚硬币a1,a2,…,ak面值和为27
所以一定有一枚最后的硬币:ak
除去这一枚硬币,前面硬币的面值和加起来是27-ak
在这里有两个关键点:
(1)关键点一:
我们不关心前面的k-1枚硬币怎么拼出27-ak的(可能有1种拼法,可能有100种),而且我们学长甚至不知道ak和k,但是我们已经确定前面的硬币拼出了27-ak
(2)关键点二:
因为是最优策略,所以拼出27-ak的硬币数一定是最少的,否则就不是最优策略了。
<2>“子问题”
(1)所以我们现在就需要求:最少用多少枚硬币可以拼出27-ak
(2)原问题是最少用多少枚硬币拼出27
(3)我们把原问题转化为了规模更小的子问题 :27-ak
(4)为了简化定义,我们设状态 f(X)=最少用多少枚硬币拼出X
Wait!!!我们还不知道最后那枚硬币ak是多少
莫慌,继续分析。
最后那枚硬币ak只可能是2,5,7
<1>如果ak=2,f(27)=f(27-2)+1
<2>如果ak=5,f(27)=f(27-5)+1
<3>如果ak=7,f(27)=f(27-7)+1
除此之外,木有其他的可能了
需要求最少的硬币数,所以:
f(27)=min{f(27-2)+1,f(27-5)+1,f(27-7)+1}
如果用递归法解题,我们画图表示一下(字有点丑,嘻嘻)
可以发现,递归解题时存在的问题
(1)做了很多重复的计算,效率低下
(2)如何避免
(3)将计算结果保存起来,并改变计算顺序
动态规划组成部分二:转移方程
(1)转移方程在面试的时候至关重要,当然也是解决问题很重要的一部分
(2)对于任意X,
f[X]=min{f[X-2]+1,f[X-5]+1,f[X-7]+1}
动态规划组成部分三:初始条件和边界情况
(1)f[X]=min{f[X-2]+1,f[X-5]+1,f[X-7]+1}
(2)两个问题:
<1> X-2, X-5, X-7小于0怎么办?
<2>什么时候停止?
(3)如果拼不出Y,就定义f[Y]=正无穷大
eg:f[-1]=f[-2]=…=正无穷大
(4)所以f[1]=min ( f[-1]+1 , f[-4]+1 , f[-6]+1)=正无穷大,表示拼不出来1
(5)初始条件:f[0] = 0
动态规划组成部分四:计算顺序
计算顺序时根据实际情况来定的
例如本题就是要先算小的,才能算出大的
即先算f[1],f[2]…f[27]
f[X]=min{f[X-2]+1,f[X-5]+1,f[X-7]+1}
对于这个式子,如果把右侧的减号改成加号,则应该先算大的
(1)每一步尝试三种硬币,一共27步
(2)与递归算法相比,木有任何重复计算
(3)算法时间复杂度(即需要进行的步数):27*3
eg2:
给定m行n列的网络,有一个机器人从左上角(0,0)出发,每一步可以向下或者向右走一步
问有多少种不同的方式走到右下角
画得好丑,哈哈哈~
【分析】
动态规划组成部分一:确定状态
-
最后一步:无论机器人用何种方式到达右下角,总有最后挪动的一步
-
右下角坐标设为(m-1,n-1)
-
那么前一步机器人一定是在(m-2,m-1)或者(m-1,n-2)
-
子问题
-
如果机器人有x种方式从左上角走到(m-2,n-1),有y种方式从左上角走到(m-1,n-2),则机器人有x+y种方式走到(m-1,n-1)
-
问题转化:机器人有多少种方式从左上角走到(m-2,n-1)和(m-1,n-2)
-
状态:设f[i][j]为机器人有多少种方式从左上角走到(i,j)
*
动态规划组成部分二:转移方程
f[i][j]=f[i-1][j]+f[i][j-1]
f[i][j] , f[i-1][j] , f[i][j-1]代表的意思如上解释
动态规划组成部分三:初始条件和边界情况
初始条件:f[0][0]=1,因为机器人只有一种方式到左上角
边界情况:i=0或者j=0,则前一步只能有一个方向过来:f[i][j]=1
动态规划组成部分四:计算顺序
f[0][0]=1
计算第0行:f[0][0],f[0][1]…f[0][n-1]
计算第1行:f[1][0],f[1][1]…f[1][n-1]
…
计算第m-1行:f[1][0],f[m-1][1]…f[m-1][n-1]
答案是f[m-1][n-1]
时间复杂度(计算步数):O(MN)
空间复杂度(数组大小):O(MN)
《小结》
动态规划组成部分:
1,确定状态
<1>研究最优策略的最后一步
<2>化为子问题
2,转移方程
根据子问题定义直接得到
3,初始条件和边界问题
细心,考虑周全
4,计算顺序
利用之前的计算结果
动态规划题目的特点
【寄语】世界的路,为自己改变;人生的路,为自己改变,做好自己就是最大的成功。希望读到这篇博文的你,能够有梦可逐!
这篇博文是我看了几个b站视频,总结感悟出来的,有什么不妥之处,欢迎大家提出!
私信,关注,评论都欢迎呀* ~ *