Skip to content

Commit

Permalink
fix: 电子书勘误 (#460)
Browse files Browse the repository at this point in the history
* fix: 电子书勘误

* Update dynamic-programming.md

Co-authored-by: lucifer <azl397985856@gmail.com>
  • Loading branch information
azl397985856 committed Nov 10, 2020
2 parents ff2cb68 + 280e47f commit f713735
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions thinkings/dynamic-programming.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

递归是指在函数的定义中使用函数自身的方法。

算法中使用递归可以很简单地完成一些用循环实现的功能,比如二叉树的左中右序遍历。递归在算法中有非常广泛的使用,包括现在日趋流行的函数式编程。
算法中使用递归可以很简单地完成一些用循环实现的功能,比如二叉树的先中后序遍历。递归在算法中有非常广泛的使用,包括现在日趋流行的函数式编程。

有意义的递归算法会把问题分解成规模缩小的同类子问题,当子问题缩减到寻常的时候,就可以知道它的解。然后建立递归函数之间的联系即可解决原问题,这也是我们使用递归的意义。准确来说, 递归并不是算法,它是和迭代对应的一种编程方法。只不过,由于隐式地借助了函数调用栈,因此递归写起来更简单。

Expand All @@ -33,7 +33,7 @@ def f(n):

### 递归中的重复计算

递归中可能存在这么多的重复计算,为了消除这种重复计算,一种简单的方式就是记忆化递归。即一边递归一边使用“记录表”(比如哈希表或者数组)记录我们已经计算过的情况,当下次再次碰到的时候,如果之前已经计算了,那么直接返回即可,这样就避免了重复计算。**动态规划中 DP 数组其实和这里“记录表”的作用是一样的**
递归中可能存在这么多的重复计算,为了消除这种重复计算,一种简单的方式就是记忆化递归。即一边递归一边使用“记录表”(比如哈希表或者数组)记录我们已经计算过的情况,当下次再次碰到的时候,如果之前已经计算了,那么直接返回即可,这样就避免了重复计算。其实在**动态规划中DP 数组和这里“记录表”的作用是一样的**

### 递归的时间复杂度分析

Expand All @@ -59,9 +59,9 @@ def f(n):

如果你已经熟悉了递归的技巧,那么使用递归解决问题非常符合人的直觉,代码写起来也比较简单。这个时候我们来关注另一个问题 - **重复计算** 。我们可以通过分析(可以尝试画一个递归树),可以看出递归在缩小问题规模的同时**是否可能会重复计算**[279.perfect-squares](../problems/279.perfect-squares.md) 中 我通过递归的方式来解决这个问题,同时内部维护了一个缓存来存储计算过的运算,这么做可以减少很多运算。 这其实和动态规划有着异曲同工的地方。

> 小提示:如果你发现并没有重复计算,那么就没有必要用记忆化递归或者动态规划了
> 小提示:如果你发现并没有重复计算,那就没有必要用记忆化递归或者动态规划
因此动态规划就是枚举所以可能。不过相比暴力枚举,动态规划不会有重复计算。因此如何保证枚举时不重不漏是关键点之一。 递归由于使用了函数调用栈来存储数据,因此如果栈变得很大,那么会容易爆栈
因此动态规划就是枚举所有可能。不过相比暴力枚举,动态规划不会有重复计算。因此如何保证枚举时不重不漏是关键点之一。 由于递归使用了函数调用栈来存储数据,因此当栈变得很大的时候,很容易就会爆栈

### 爆栈

Expand Down Expand Up @@ -94,7 +94,7 @@ function sum(nums) {

> [746. 使用最小花费爬楼梯](https://leetcode-cn.com/problems/min-cost-climbing-stairs/) 是这道题的换皮题, GrowingIO 前端工程师岗位考察过这个题目。
由于上第 n 级台阶一定是从 n - 1 或者 n - 2 来的,因此 上第 n 级台阶的数目就是 `上 n - 1 级台阶的数目加上 n - 1 级台阶的数目`
由于上第 n 级台阶一定是从 n - 1 或者 n - 2 来的,因此 上第 n 级台阶的数目就是 `(n - 1) 级台阶的数目「加」上 (n - 2) 级台阶的数目`

递归代码:

Expand Down Expand Up @@ -152,7 +152,7 @@ function dp(n) {
这道题目是动态规划中最简单的问题了,因为只涉及到单个因素的变化,如果涉及到多个因素,就比较复杂了,比如著名的背包问题,挖金矿问题等。

对于单个因素的,我们最多只需要一个一维数组即可,对于如背包问题我们需要二维数组等更高纬度
对于单个因素的,我们最多只需要一个一维数组即可,对于如背包问题我们需要二维甚至更高维度的数组

爬楼梯我们并没有必要使用一维数组,而是借助两个变量来实现的,空间复杂度是 O(1)。代码:

Expand Down Expand Up @@ -220,7 +220,7 @@ dp[n] = dp[n - 1] + dp[n - 2] 就是【状态转移方程】

#### 状态转移方程

爬楼梯问题由于上第 n 级台阶一定是从 n - 1 或者 n - 2 来的,因此 上第 n 级台阶的数目就是 `上 n - 1 级台阶的数目加上 n - 1 级台阶的数目`
爬楼梯问题由于上第 n 级台阶一定是从 n - 1 或者 n - 2 来的,因此 上第 n 级台阶的数目就是 `(n - 1) 级台阶的数目「加」上 (n - 2) 级台阶的数目`

上面的这个理解是核心, 它就是我们的状态转移方程,用代码表示就是 `f(n) = f(n - 1) + f(n - 2)`

Expand Down

0 comments on commit f713735

Please sign in to comment.