动态规划题型总结
来源:互联网 发布:终极算法 pdf 编辑:程序博客网 时间:2024/05/17 04:40
三个重要概念:最优子结构、边界、状态转移方程
动态规划特征:
(1)最优子结构:如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。意思就是,总问题包含很多个子问题,而这些子问题的解也是最优的。
(2)重叠子问题:子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的效率。
1、台阶问题:有一座高度是10级台阶的楼梯,从下往上走,每跨一步只能向上1级或2级台阶,要求用程序来求出一共有多少种走法?
解法:设f(10)为到第10阶台阶的走法数,那么f(10)=f(8)+f(9), f(8)和f(9)即为f(10)的最优子结构, 可以看出是一个斐波那契数列,更一般地,f(i) = f(i-2)+f(i-1),边界值f(1)=1,f(2)=2,那么状态转移方程如下:
f(1) = 1,
f(2) = 2,
f(n) = f(n-1) + f(n-2) (n>=3).
分析:用递归方法求解时,在递归树上有很多结点是重复的,而且重复的结点数会随着n的增大而急剧增大,计算量也会随之增大,所以用递归方法的时间复杂度是以n的指数的方式递增的。所以不能使用递归求解,优化的方向是怎样避免计算重复值,所以更好的方法是自底向上计算,这样前面计算过的就不用再重复计算了。
代码实现:
时间复杂度:O(n)
2、变态台阶问题:有n阶台阶,一只青蛙可以跳上1级台阶,也可以跳上2级台阶...也可以跳上n级,此时青蛙跳上一个n级的台阶总共有多少种跳法?
解法:设f(n)为青蛙跳上n阶台阶的跳法数,f(4-1)为4阶台阶下有一次跳1阶台阶的跳法数,可以知道四级台阶下有一次选择跳1阶的跳法数f(4-1)等于3级台阶的所有跳法数f(3),所以f(4-1)=f(3),那么
f(0) = 1;
f(1) = 1;
f(2) = f(2-1)+f(2-2) = f(1)+f(0);
f(3) = f(3-1)+f(3-2)+f(3-3) = f(2)+f(1)+f(0)
.....
f(n) = f(n-1)+ f(n-2)+...+f(2)+f(1) +f(0) (1) (n>=0)
f(n-1) = f(n-2) +f(n-1)+...+f(2)+f(1) +f(0) (2) (n>=1)
(1)-(2)得到:f(n) = 2f(n-1)=4f(n-2)=..=2^(n-1)f(1)=2^(n-1) (n>=1)
代码实现:
时间复杂度:O(n)
3、最长递增子序列问题:给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4.
解法1:设数组为array,以array[j]结尾的最长递增子序列为L[j],那么L[j] = max(L[i])+1, 其中 0=<i<j,array[j]>array[i],L[0]=1,这样求得所有L[j](0<=j<=array.length-1)后,比较所有的L[j]可获得最长单调递增子序列的长度,如代码实现1所示。如果还需要求得最长递增子序列,需要用一个数组保存以每个元素i结尾的递增子序列,如果有多个最长递增子序列,暂时只能求得一个子序列,如代码实现2所示。
代码实现1:求最长单调递增子序列的长度。
时间复杂度:O(n^2)
代码实现2:求最长单调递增子序列的长度和一个最长递增子序列。
4、最长公共子序列问题:求两个或多个已知数列最长的子序列。
解法:运用自底向上的填表格法编码,设x[1...m]和y[1...n],c[i,j]为x[1...i]和y[1..j]的最长公共子序列的长度,那么
c[i,j] = c[i-1,j-1] if x[i] = x[j]
c[i,j] = max{c[i-1,j],c[i,j-1]} otherwise
最后用在表格中用标记回溯法返回所有的最长公共子序列。
表格例子:
A
B
C
B
D
A
B
0
0
0
0
0
0
0
0
B
0
0
1
1
1
1
1
1
D
0
0
1
1
1
2
2
2
C
0
0
1
2
2
2
2
2
A
0
1
1
2
2
2
3
3
B
0
1
2
2
3
3
3
4
A
0
1
2
2
3
3
4
4
代码实现:
时间复杂度:O(m*n)
5、连续子数组和最大问题:一个整数数组中的元素有正有负,在该数组中找出一个连续子数组,要求该连续子数组中各元素的和最大,这个连续子数组便被称作最大连续子数组。比如数组{2,4,-7,5,2,-1,2,-4,3}的最大连续子数组为{5,2,-1,2},最大连续子数组的和为5+2-1+2=8。
解法:设数组为array,以array[i]结尾的最大连续子数组和为dp[i],那么dp[i]=dp[i-1]>0?dp[i-1]:0+array[i],其中0<=i<=array.length-1,dp[0]=array[0],最后比较所有的dp[i],其中最大的一个即为最大连续子数组和。
代码实现:
时间复杂度:O(n)
6、背包问题:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。
7、股票问题:3种变形
8、编辑距离问题:求两个字串之间,由一个转成另一个所需的最少编辑操作次数。编辑操作包括替换、插入、删除一个字符。一般来说,编辑距离越小,两个串的相似度越大。
9、字符串对齐问题:两个字符串中相同的字符串彼此对应的最小花费?
注:代码均为手写输入,可能有错,其他动态规划问题未完待续
- 动态规划题型总结
- 动态规划 所有题型的总结
- 动态规划常见题型
- 动态规划-经典题型
- 动态规划算法常见题型
- 动态规划,poj几道基础经典题型,重要!
- 动态规划DP问题分类和经典题型
- 动态规划DP问题分类和经典题型
- 动态规划总结
- 动态规划总结
- 【转】动态规划总结
- 动态规划总结
- 动态规划总结
- 动态规划总结
- noip动态规划总结
- 动态规划总结
- 动态规划总结
- 动态规划总结
- C++ 运算符重载和拷贝构造
- Proiect Euler problem 4 : Largest palindrome product
- module.exports与exports,export与export default之间的关系和区别
- [Qt] 我的一款射击游戏及设计模式
- MapReducer优化
- 动态规划题型总结
- BigDecimal保留两位小数及格式化成百分比
- nginx模块解析
- swift get、set、willSet和didSet
- Linked List Cycle II
- Android 7.0 行为变更 通过FileProvider在应用间共享文件吧
- 框架学习之spring整合hibernate、struts2框架-01基础配置
- SQL 使用update case when 批量更新
- 多重背包的二进制优化