Skip to content

Commit 0d024ca

Browse files
committed
add Dynamic Programming
1 parent 2897d74 commit 0d024ca

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed

基础算法篇/动态规划.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
### 动态规划
2+
3+
#### 背景
4+
5+
先从一道题目开始~
6+
7+
如题 [triangle](https://leetcode-cn.com/problems/triangle/)
8+
9+
> 给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
10+
11+
例如,给定三角形:
12+
13+
```js
14+
[
15+
[2],
16+
[3,4],
17+
[6,5,7],
18+
[4,1,8,3]
19+
]
20+
```
21+
22+
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
23+
24+
使用 DFS(遍历 或者 分治法)
25+
26+
超时
27+
28+
```js
29+
var row = 0;
30+
31+
var minimumTotal = function(tringle){
32+
row = tringle.length;
33+
return helper(0,0,tringle);
34+
}
35+
36+
var helper = function(level, c, tringle){
37+
if (level === row-1) {
38+
return tringle[level][c];
39+
}
40+
let left = helper(level+1, c, tringle);
41+
let right = helper(level+1, c+1, tringle);
42+
return Math.min(left,right) + tringle[level][c];
43+
}
44+
45+
let tringle = [
46+
[2],
47+
[3,4],
48+
[6,5,7],
49+
[4,1,8,3]
50+
];
51+
52+
console.log(minimumTotal(tringle)); //11
53+
```
54+
55+
动态规划就是把大问题变成小问题,并解决了小问题重复计算的方法称为动态规划
56+
57+
动态规划和 DFS 区别
58+
59+
- 二叉树 子问题是没有交集,所以大部分二叉树都用递归或者分治法,即 DFS,就可以解决
60+
- 像 triangle 这种是有重复走的情况,**子问题是有交集**,所以可以用动态规划来解决
61+
62+
**动态规划三个特性**
63+
64+
- 最优子结构
65+
66+
最优子结构指的是,问题的最优解包含子问题的最优解。反过来说就是,我们可以通过子问题的最优解,推导出问题的最优解。如果我们把最优子结构,对应到我们前面定义的动态规划问题模型上,那我们也可以理解为,后面阶段的状态可以通过前面阶段的状态推导出来。
67+
68+
- 无后效性
69+
70+
无后效性有两层含义,第一层含义是,在推导后面阶段的状态的时候,我们只关心前面阶段的状态值,不关心这个状态是怎么一步一步推导出来的。第二层含义是,某阶段状态一旦确定,就不受之后阶段的决策影响。无后效性是一个非常“宽松”的要求。只要满足前面提到的动态规划问题模型,其实基本上都会满足无后效性。
71+
72+
- 重复子问题
73+
74+
如果用一句话概括一下,那就是,不同的决策序列,到达某个相同的阶段时,可能会产生重复的状态。所以才会用一个数组记录中间结果,避免重复计算。
75+
76+
动态规划,自底向上 这里变成一位数组,因为层号实际上可以不用记录,每次记录上一层的值,到当前层就把以前的覆盖到,动态规划运用场景其中一条就是最优子结构,往下走不用回头一定是最优的
77+
78+
```js
79+
var minimumTotal = function(tringle){
80+
let row = tringle.length;
81+
let dp = new Array(row+1).fill(0);
82+
for (let level = row-1;level>=0;level--){
83+
for (let i = 0; i <= level; i++) { //第i行有i个数
84+
dp[i] = Math.min(dp[i],dp[i+1]) + tringle[level][i];
85+
}
86+
}
87+
return dp[0];
88+
}
89+
```
90+
91+
## 递归和动规关系
92+
93+
递归是一种程序的实现方式:函数的自我调用
94+
95+
```
96+
Function(x) {
97+
...
98+
Funciton(x-1);
99+
...
100+
}
101+
```
102+
103+
动态规划:是一种解决问 题的思想,大规模问题的结果,是由小规模问 题的结果运算得来的。动态规划可用递归来实现(Memorization Search)
104+
105+
## 使用场景
106+
107+
满足三个条件:最优子结构,无后效性,重复子问题
108+
109+
简单来说就是:
110+
111+
- 满足以下条件之一
112+
- 求最大/最小值(Maximum/Minimum )
113+
- 求是否可行(Yes/No )
114+
- 求可行个数(Count(*) )
115+
- 满足不能排序或者交换(Can not sort / swap )
116+
117+
如题:[longest-consecutive-sequence](https://leetcode-cn.com/problems/longest-consecutive-sequence/) 位置可以交换,所以不用动态规划
118+
119+
## 四点要素
120+
121+
1. 状态 State
122+
- 灵感,创造力,存储小规模问题的结果
123+
2. 方程 Function
124+
- 状态之间的联系,怎么通过小的状态,来算大的状态
125+
3. 初始化 Intialization
126+
- 最极限的小状态是什么, 起点
127+
4. 答案 Answer
128+
- 最大的那个状态是什么,终点
129+
130+
## 常见四种类型
131+
132+
1. Matrix DP (10%)
133+
2. Sequence (40%)
134+
3. Two Sequences DP (40%)
135+
4. Backpack (10%)
136+
137+
> 注意点
138+
>
139+
> - 贪心算法大多题目靠背答案,所以如果能用动态规划就尽量用动规,不用贪心算法

0 commit comments

Comments
 (0)