多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 动态规划 > 原文: [https://www.programiz.com/dsa/dynamic-programming](https://www.programiz.com/dsa/dynamic-programming) #### 在本教程中,您将学习什么是动态规划。 此外,您还将发现动态规划和贪婪算法之间的比较,以解决问题。 动态规划是计算机编程中的一种技术,可帮助有效解决一类具有重叠子问题和[最佳子结构](https://en.wikipedia.org/wiki/Optimal_substructure)属性的问题。 这些问题涉及重复计算相同子问题的值以找到最佳解决方案。 * * * ## 动态规划实例 以生成斐波那契数列为例。 如果序列是`F(1)F(2)F(3)........ F(50)`,则遵循规则`F(n) = F(n-1) + F(n-2)`) ``` F(50) = F(49) + F(48) F(49) = F(48) + F(47) F(48) = F(47) + F(46) ... ``` 注意,子问题如何重叠,我们需要计算`F(48)`才能计算`F(50)`和`F(49)`。 这正是动态规划大放异彩的算法。 * * * ## 动态规划的工作原理 动态规划通过存储子问题的结果来工作,以便在需要它们的解决方案时就可以使用它们,而我们无需重新计算它们。 这种存储子问题值的技术称为记忆。 通过将值保存在数组中,我们节省了计算遇到的子问题的时间。 ``` var m = map(0 → 0, 1 → 1) function fib(n) if key n is not in map m m[n] = fib(n − 1) + fib(n − 2) return m[n] ``` 通过备注进行动态规划是一种自顶向下的动态规划方法。 通过反转算法的工作方向,即从基本情况开始并朝解决方案努力,我们还可以自下而上地实现动态规划。 ``` function fib(n) if n = 0 return 0 else var prevFib = 0, currFib = 1 repeat n − 1 times var newFib = prevFiB+ currFib prevFib = currFib currFib = newFib return currentFib ``` * * * ## 递归与动态规划 动态规划主要应用于递归算法。 这不是巧合,大多数优化问题都需要递归,并且将动态规划用于优化。 但是并非所有使用递归的问题都可以使用动态规划。 除非像斐波那契数列问题那样存在重叠的子问题,否则递归只能使用分治的方法来解决。 这就是为什么诸如归并排序的递归算法不能使用动态规划的原因,因为子问题不会以任何方式重叠。 * * * ## 贪婪算法与动态规划 [贪婪算法](https://www.programiz.com/dsa/greedy-algorithm)与动态规划类似,因为它们都是优化工具。 但是,贪婪算法会寻找局部最优解,或者换句话说,是贪婪的选择,以期找到全局最优解。 因此,贪婪的算法可能会做出一个猜测,即看起来当时是最优的,但代价很高,并且不能保证全局最优。 另一方面,动态规划会找到子问题的最佳解决方案,然后做出明智的选择,以合并那些子问题的结果以找到最佳解决方案。