动态规划详解
作者:互联网
一、名词解释
动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果 。(引自百度百科)
动态规划最核心的思想,就在于拆分子问题,记住过往,减少重复计算。
二、举例说明
LeetCode的题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总共有多少种跳法。
解析:
要想跳到第10级台阶,要么是先跳到第9级,然后再跳1级台阶上去;要么是先跳到第8级,然后一次迈2级台阶上去。
要想跳到第9级台阶,要么是先跳到第8级,然后再跳1级台阶上去;要么是先跳到第7级,然后一次迈2级台阶上去。
...
要想跳到第2级台阶,要么是先跳到第1级,然后再跳1级台阶上去;要么是一次迈2级台阶上去。
要想跳到第1级台阶,一次迈1级台阶上去。
依此类推:
f(10) = f(9)+f(8)
f (9) = f(8) + f(7)
f (8) = f(7) + f(6)
...
f (2) = 2
f (1) = 1
此时可以用递归的方式:
class Solution {
public int numWays(int n) {
if(n == 1){
return 1;
}
if(n == 2){
return 2;
}
return numWays(n-1) + numWays(n-2);
}
}
但是这样会有大量的重复计算,我们可以进行优化一下,把一些重复的进行缓存。空间复杂度是O(n)。
public class Solution {
//使用map缓存
Map<Integer, Integer> tempMap = new HashMap();
public int numWays(int n) {
if (n == 0) {
return 1;
}
if (n <= 2) {
return n;
}
if (tempMap.containsKey(n)) {
return tempMap.get(n);
} else {
tempMap.put(n, (numWays(n - 1) + numWays(n - 2)));
return tempMap.get(n);
}
}
}
上面是自上而下的递归结合map起到缓存的作用,用动态规划就是自下而上进行计算。空间复杂度是O(1)。
public class Solution {
public int numWays(int n) {
if (n<= 1) {
return 1;
}
if (n == 2) {
return 2;
}
int a = 1;
int b = 2;
int temp = 0;
for (int i = 3; i <= n; i++) {
temp = a + b;
a = b;
b = temp;
}
return temp;
}
}
总结:
1.首先可以用穷举法进行分析
2.找出特殊的跳法(边界值)
3.找出规律,确定最优子结构
4.写出伪代码,进行实现
使用场景:
如果一个问题,可以把所有可能的答案穷举出来,并且穷举出来后,发现存在重叠子问题,就可以考虑使用动态规划,
比如一些求最值的场景,如最长递增子序列、最小编辑距离、背包问题、凑零钱问题等等,都是动态规划的经典应用场景。
标签:numWays,台阶,int,要么,详解,动态,规划,public 来源: https://blog.csdn.net/qq382495414/article/details/116700632