每日算法-动态规划
Posted 前端启示录
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日算法-动态规划相关的知识,希望对你有一定的参考价值。
“ 2020年计划,每周5道算法题,由简到难,期待2021年的自己。”
动态规划(Dynamic Programming)
动态规划(dynamic programming)是解决多阶段决策问题常用的最优化理论。
该理论由美国数学家 Bellman等人在1957年提出,用于研究多阶段决策过程的优化问题。该理论提出后,立即在数学、计算机科学、经济管理和工程技术领域得到了广泛的应用,例如,最短路线、库存管理、资源分配、设备更新、排序装载等问题。
用动态规划方法往往比朴素的方法更高效。动态规划方法的原理就是把多阶段决策过程转化为一系列的单阶段决策问题。利用各个阶段之间的递推关系,逐个确定每个阶段的最优化决策。最终堆叠出多阶段决策的最优化决策结果
为什么要用动态规划
因为动态规划要比穷举更加高效。穷举的时间复杂度是指数级的。动态规划的时间复杂度要简单的多。之后我们在题目中再做分析。
如何使用动态规划
首先我们要明确一点,每种方法都有其局限性,动态规划也不是万能的。动态规划适合求解多阶段(状态转换)决策问题的最优解。
是否能使用动态规划来解决,看其是否满足最优化原理和子问题的无后向性。
最优化原理(最优子结构性质) :最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。
无后向性 :将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。
实现方式:
自顶向下备忘录方式:保存子问题的结果,之后在求解某个子问题时,若其用到的某个子问题且已经保存了结果,直接返回。
自底向上: 在求某个子问题时,会依赖已经求出的更小的子问题的解。
第一种方法符合平常的思维模式。第二种和第一种正好相反。
最优子结构
边界
状态转移公式
说的多了不理解都是废话,拿题来练。我们先来一个最简单的题目。
爬台阶
F[ 1 ] = 1;
F 2 ] = 2;
F[ n ] = F[ n-1 ] + F[ n-2 ]
function climbStairs(n) {
if (n === 0 || n ===1 || n ===2) {
return n;
}
// 一直递归搜索
return climbStairs(n - 1) + climbStairs(n - 2);
}
climbStairs(40);
代码实现如下:
复杂度分析
时间复杂度:O(n),树形递归的大小可以达到 n。
空间复杂度:O(n),递归树的深度可以达到 n。
备忘录法可以极大程度上降低我们的时间复杂度。
动态规划法
我们使用动态规划需要了解三个重要的概念。
最优子结构
边界
状态转移公式
在第8台阶 上2阶 到达
在第9台阶 上1阶 到达 到达
F(10) = F(9)+F(8)
按照刚才的思路接着往下推算
F(9) = F(8)+F(7) F(8) = F(7)+F(6) ······
最优子结构 :F(10) = F(9)+F(8) F(9) 和 F(8) 就是 F(10)的最优子结构
边界:思考当只有一阶台阶的时候,我们只有一中方式,就是迈一步, 当只有二阶台阶的时候,我们有两种方式,1+1 或者 2。 所以F(1) 和 F(2) 就是当前问题的边界。 如果一个问题没有边界,那将永远无法得到有限的结果
状态转移公式:按照上面的推理过程我们可以总结出 F(n) = F(n-1)+F(n-2) 状态转移公式是动态规划的核心,决定了问题的每一个阶段和下一阶段的关系。
自顶向下的解法:
(PS.页面排版突然不能插入代码了,就只能插图片了┓( ´∀` )┏)
以上是关于每日算法-动态规划的主要内容,如果未能解决你的问题,请参考以下文章