我在学习的时候经常搞不清楚递归和动态规划,所以这里区分一下。
递归:程序调用自身,从顶部将问题分解,通过解决掉所有分解出来的小问题,来解决整个问题。一般是函数的返回调用,运行时间较长。
f(n)
=f(n-1)+f(n-2)
=f(n-2)+f(n-3)+f(n-3)+f(n-4)
=…
迭代:利用变量的原值推算出变量的一个新值。递归中一定有迭代,但是迭代中不一定有递归。
f(3)=f(2)+f(1)
f(4)=f(3)+f(2)
f(5)=f(4)+f(3)
动态规划:
解决多阶段决策问题,要求无后效性,解决思路通常与递归相反,其从底部开始解决问题。将所有小问题解决掉,进而解决最终的问题。
空间换时间的方法,解存储在一张表格里,这样每个子问题只用计算一次。
动态规划经典题型:
1.台阶问题:
有n级台阶,一个人每次上一级或者两级,问有多少种走完n级台阶的方法。
思路:这是一个非常经典的为题,设f(n)为上n级台阶的方法,要上到n级台阶的最后一步有两种方式:从n-1级台阶走一步;从n-1级台阶走两步,于是就有了这个公式f(n) = f(n-1)+f(n-2);用数组dp存储到达每节楼梯的走法种类。
2.最长公共序列数
给定两个字符串A和B,返回两个字符串的最长公共子序列的长度。例如,A="1A2C3D4B56”,B="B1D23CA45B6A”,”123456"或者"12C4B6"都是最长公共子序列。
给定两个字符串A和B,同时给定两个串的长度n和m,请返回最长公共子序列的长度。保证两串长度均小于等于300。
测试样例:
“1A2C3D4B56”,10,“B1D23CA45B6A”,12
返回:6
解析:设dp[n][m] ,为A的前n个字符与B的前m个字符的公共序列长度,则当A[n]==B[m]的时候,dp[i][j] = max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]),否则,dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
3.走方格问题
有一个矩阵map,它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。
解析:设dp[n][m]为走到n*m位置的路径长度,那么显而易见dp[n][m] = min(dp[n-1][m],dp[n][m-1]);
4. 找零钱问题
有数组penny,penny中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。
给定数组penny及它的大小(小于等于50),同时给定一个整数aim,请返回有多少种方法可以凑成aim。
解析:设dp[n][m]为使用前n种货币凑成的m的种数,那么就会有两种情况: 使用第n种货币:dp[n-1][m]+dp[n-1][m-peney[n]]
不用第n种货币:dp[n-1][m]
为什么不使用第n种货币呢,因为penney[n]>m。
这样就可以求出当m>=penney[n]时 dp[n][m] = dp[n-1][m]+dp[n][m-peney[n]],否则,dp[n][m] = dp[n-1][m]
还有:
1. 国王和金矿
2. 计算矩阵连乘积
3. 凸多边形的最优三角剖分
4. 防卫导弹
5. 石子合并
6. 最小代价子母树
7. 商店购物
8. 旅游预算
9. 皇宫看守
(之后再写啦~)