提交 f81d43a0 编写于 作者: W wizardforcel

2020-07-09 18:43:54

上级 a14acbc3
......@@ -491,7 +491,7 @@ int main() {
## 优先队列应用
优先队列的一些应用程序是:
优先队列的一些应用是:
* Dijkstra 算法
* 用于实现栈
......
......@@ -2,7 +2,7 @@
> 原文: [https://www.programiz.com/dsa/linked-list](https://www.programiz.com/dsa/linked-list)
#### 在本教程中,您将学习链表及其应用程序。 您还将学习如何在链表上创建和执行不同的操作。
#### 在本教程中,您将学习链表及其应用。 您还将学习如何在链表上创建和执行不同的操作。
在寻宝游戏中,您首先要寻找第一个线索。 当您找到它时,它不再具有宝藏,而是具有下一条线索的位置,依此类推。 您会一直遵循这些线索,直到找到宝藏为止。
......
......@@ -32,7 +32,7 @@ Full Binary Tree
### 完美二叉树
完美二叉树是一种二叉树,其中每个内部节点恰好有两个子节点,而所有叶节点都处于同一级别。
完美二叉树是一种二叉树,其中每个内部节点恰好有两个子节点,而所有叶节点都处于同一级别。
![Perfect binary tree](img/2166820fd9f04e3185cca16b87512e32.png "Perfect binary tree")
......
# 完美二叉树
# 完美二叉树
> 原文: [https://www.programiz.com/dsa/perfect-binary-tree](https://www.programiz.com/dsa/perfect-binary-tree)
#### 在本教程中,您将学习完美的二叉树。 此外,您还将找到一些用于检查 C,C++ ,Java 和 Python 中完美的二叉树的示例。
#### 在本教程中,您将学习完美二叉树。 此外,您还将找到一些用于检查 C,C++ ,Java 和 Python 中完美二叉树的示例。
完美二叉树是一种二叉树,其中每个内部节点恰好有两个子节点,而所有叶节点都处于同一级别。
完美二叉树是一种二叉树,其中每个内部节点恰好有两个子节点,而所有叶节点都处于同一级别。
![Perfect Binary Tree](img/2166820fd9f04e3185cca16b87512e32.png "Perfect Binary Tree")
......@@ -14,7 +14,7 @@ Perfect Binary Tree
所有内部节点的度数均为 2。
递归地,可以将完美二叉树定义为:
递归地,可以将完美二叉树定义为:
1. 如果单个节点没有子节点,则它是高度为`h = 0`的完美二叉树,
2. 如果节点具有`h > 0`,则如果其两个子树的高度均为`h - 1`并且不重叠,则它是理想的二叉树。
......@@ -29,7 +29,7 @@ Perfect Binary Tree (Recursive Representation)
## Python,Java 和 C/C++ 示例
以下代码用于检查树是否是完美二叉树。
以下代码用于检查树是否是完美二叉树。
[Python](#python-code)[Java](#java-code)[C](#c-code)[C++](#cpp-code)
......
......@@ -163,7 +163,7 @@ Avl tree
* * *
## 插入`newNode`的算法
## 插入新节点的算法
`newNode`始终作为平衡因子等于 0 的叶节点插入。
......@@ -1077,7 +1077,7 @@ int main() {
* * *
## AVL 树上不同操作的复杂度
## AVL 树上不同操作的复杂度
| **插入** | **删除** | **搜索** |
| --- | --- | --- |
......
......@@ -38,9 +38,9 @@ B-tree
* * *
## 运作方式
## 工作原理
### 正在搜寻
### 搜索
在 B 树中搜索元素是在二叉搜索树中搜索元素的一般形式。 遵循以下步骤。
......@@ -53,7 +53,7 @@ B-tree
否则,搜索键的右子级。
5. 重复步骤 1 到 4,直到到达叶子。
### 搜寻范
### 搜索示
1. 让我们在等级 3 下面的树中搜索关键字`k = 17`
......@@ -761,7 +761,7 @@ int main() {
* * *
## 在 B 树上搜索复杂度
## B 树上的搜索的复杂度
最坏情况下的时间复杂度:`Θ(log n)`
......
......@@ -47,7 +47,7 @@ B+ 树上的操作比 B 树上的操作快。
* * *
## 在 B+ 树上搜索
## B+ 树上的搜索
遵循以下步骤以在顺序为`m`的 B+ 树中搜索数据。 令要搜索的数据为`k`
......@@ -60,7 +60,7 @@ B+ 树上的操作比 B 树上的操作快。
* * *
## 在 B+ 树上搜索示例
## B+ 树上的搜索示例
让我们在以下 B+ 树上搜索`k = 45`
......
......@@ -213,7 +213,7 @@ Red Black Tree
* * *
### 插入后保持红黑性的算法
### 插入后保持红黑性的算法
如果`newNode`的插入违反了此属性,则此算法用于维护红黑树的属性。
......
......@@ -64,7 +64,7 @@
* * *
## 删除后保持 Red-Black 属性的算法
## 删除后保持红黑属性的算法
当删除黑色节点时会执行此算法,因为它违反了红黑树的黑色深度属性。
......
# 图数据结构
# 图数据结构
> 原文: [https://www.programiz.com/dsa/graph](https://www.programiz.com/dsa/graph)
#### 在本教程中,您将学习什么是图形数据结构。 此外,您还将找到图形的表示形式。
#### 在本教程中,您将学习什么是图数据结构。 此外,您还将找到图的表示形式。
数据结构是具有数据并连接到其他节点的节点的集合。
图数据结构是具有数据并连接到其他节点的节点的集合。
让我们尝试通过一个例子来理解这一点。 在 facebook 上,一切都是节点。 包括用户,照片,相册,事件,组,页面,评论,故事,视频,链接,注释...任何有数据的都是节点。
......@@ -16,7 +16,7 @@ Example of graph data structure
然后,所有的 facebook 都是这些节点和边的集合。 这是因为 facebook 使用图数据结构来存储其数据。
然后,所有的 facebook 都是这些节点和边的集合。 这是因为 facebook 使用图数据结构来存储其数据。
更准确地说,图是一种数据结构`(V, E)`,由
......@@ -39,7 +39,7 @@ G = {V, E}
* * *
## 图术语
## 图术语
* **相邻**:如果存在一条连接顶点的边,则该顶点被称为与另一个顶点相邻。 顶点 2 和 3 不相邻,因为它们之间没有边。
* **路径**:一条允许您从顶点`A`到顶点`B`的边序列称为路径。 0-1、1-2 和 0-2 是从顶点 0 到顶点 2 的路径。
......@@ -47,7 +47,7 @@ G = {V, E}
* * *
## 图表示
## 图表示
图通常以两种方式表示:
......@@ -87,11 +87,11 @@ Adjacency list representation
* * *
## 图操作
## 图操作
最常见的图操作是:
最常见的图操作是:
* 检查图中是否存在该元素
* 图的遍历
* 向图添加元素(顶点,边)
* 向图添加元素(顶点,边)
* 寻找从一个顶点到另一个顶点的路径
\ No newline at end of file
......@@ -30,9 +30,9 @@ Strongly connected components
* * *
## Kosaraju 算法
## Kosaraju 算法
Kosaraju 算法基于[两次实现的深度优先搜索算法](/dsa/graph-dfs)
Kosaraju 算法基于[两次实现的深度优先搜索算法](/dsa/graph-dfs)
涉及三个步骤。
......@@ -412,9 +412,9 @@ int main() {
* * *
## Kosaraju 算法复杂度
## Kosaraju 算法复杂度
Kosaraju 算法在线性时间即`O(V+E)`中运行。
Kosaraju 算法在线性时间即`O(V+E)`中运行。
* * *
......
# 广度优先搜索
# BFS 算法
> 原文: [https://www.programiz.com/dsa/graph-bfs](https://www.programiz.com/dsa/graph-bfs)
......
# 贝尔曼·福特算法
# Bellman Ford 算法
> 原文: [https://www.programiz.com/dsa/bellman-ford-algorithm](https://www.programiz.com/dsa/bellman-ford-algorithm)
#### Bellman Ford 算法可帮助我们找到从一个顶点到加权图的所有其他顶点的最短路径。
它类似于 [Dijkstra 算法](/dsa/dijkstra-algorithm),但它可以用于边的权重为负的图形。
它类似于 [Dijkstra 算法](/dsa/dijkstra-algorithm),但它可以用于边的权重为负的图形。
* * *
## 为什么人们在现实生活中会遇到负重的边?
## 为什么人们在现实生活中会遇到负重的边?
起初负负边似乎没有用,但它们可以解释很多现象,例如现金流,化学反应中释放/吸收的热量等。
......@@ -18,7 +18,7 @@
* * *
## 为什么我们需要小心负重?
## 为什么我们需要小心负重?
负权重边会产生负权重循环,即,一个循环将通过返回同一点来减少总路径距离。
......@@ -76,7 +76,7 @@ Step-6 for Bellman Ford's algorithm
* * *
## 贝尔曼·福特伪代码
## Bellman Ford 伪代码
我们需要保持每个顶点的路径距离。 我们可以将其存储在大小为`v`的数组中,其中`v`是顶点数。
......@@ -107,7 +107,7 @@ function bellmanFord(G, S)
* * *
## 贝尔曼·福特 vs 迪克斯特拉
## Bellman Ford vs Dijkstra
Bellman Ford 算法和 Dijkstra 算法在结构上非常相似。 虽然 Dijkstra 仅查找顶点的直接邻居,但 Bellman 会在每次迭代中遍历每个边。
......@@ -565,7 +565,7 @@ int main() {
* * *
## 贝尔曼·福特的复杂度
## Bellman Ford 的复杂度
### 时间复杂度
......@@ -581,7 +581,7 @@ int main() {
* * *
## 贝尔曼·福特算法应用
## Bellman Ford 算法应用
1. 用于计算路由算法中的最短路径
2. 寻找最短路径
\ No newline at end of file
# 泡排序算法
# 泡排序算法
> 原文: [https://www.programiz.com/dsa/bubble-sort](https://www.programiz.com/dsa/bubble-sort)
#### 在本教程中,您将学习泡排序的工作原理。 此外,您还将找到 C,C++ ,Java 和 Python 中冒泡排序的工作示例。
#### 在本教程中,您将学习泡排序的工作原理。 此外,您还将找到 C,C++ ,Java 和 Python 中冒泡排序的工作示例。
冒泡排序是一种算法,用于比较相邻元素,如果相邻元素之间的位置不符合预期顺序,则会交换它们的位置。 顺序可以是升序或降序。
* * *
## 泡排序如何工作?
## 泡排序如何工作?
1. 从第一个索引开始,比较第一个和第二个元素,如果第一个元素大于第二个元素,则将它们交换。
......@@ -50,7 +50,7 @@
* * *
## 泡排序算法
## 泡排序算法
```
bubbleSort(array)
......@@ -211,7 +211,7 @@ int main() {
* * *
## 优化泡排序
## 优化泡排序
在上面的代码中,即使数组已经排序,也进行了所有可能的比较。 它增加了执行时间。
......@@ -219,7 +219,7 @@ int main() {
在这种情况下,将变量`swapped`设置为`false`。 因此,我们可以防止进一步的迭代。
优化泡排序的算法是
优化泡排序的算法是
```
bubbleSort(array)
......@@ -415,9 +415,9 @@ int main() {
* * *
## 复杂
## 复杂
泡排序是最简单的排序算法之一。 该算法实现了两个循环。
泡排序是最简单的排序算法之一。 该算法实现了两个循环。
| 周期 | 比较次数 |
| --- | --- |
......@@ -451,7 +451,7 @@ int main() {
* * *
## 泡排序应用
## 泡排序应用
在以下情况下使用冒泡排序:
......
......@@ -246,7 +246,7 @@ int main() {
* * *
## 复杂
## 复杂
| 周期 | 比较次数 |
| --- | --- |
......
......@@ -6,7 +6,7 @@
插入排序的工作方式与我们在纸牌游戏中对手牌进行排序的方式类似。
我们假设第一张卡片已经被排序,那么我们选择一个未排序的卡片。 如果未分类的卡片大于手中的卡片,则将其放置在右侧,否则放置在左侧。 同样,其他未分类的卡片也会被拿到正确的位置。
我们假设第一张卡片已经被排序,那么我们选择一个未排序的卡片。 如果未排序的卡片大于手中的卡片,则将其放置在右侧,否则放置在左侧。 同样,其他未排序的卡片也会被拿到正确的位置。
插入排序使用类似的方法。
......@@ -225,7 +225,7 @@ int main() {
* * *
## 复杂
## 复杂
**时间复杂度**
......
......@@ -167,7 +167,7 @@ Merging two consecutive subarrays of array
数组`A[0..5]`包含两个分类的子数组`A[0..3]``A[4..5]`。 让我们看看`merge`函数如何合并两个数组。
数组`A[0..5]`包含两个排序的子数组`A[0..3]``A[4..5]`。 让我们看看`merge`函数如何合并两个数组。
```
void merge(int arr[], int p, int q, int r) {
......@@ -213,7 +213,7 @@ Maintain indices of copies of sub array and main array
### 步骤 3:直到我们到达`L`或`M`的尽头,在元素`L`和`M`中选择更大的一个,并将其放置`A[p..r]`的正确位置
### 步骤 3:直到我们到达`L`或`M`的尽头,在元素`L`和`M`中选择更大的一个,并将其放置`A[p..r]`的正确位置
```
while (i < n1 && j < n2) {
......@@ -234,7 +234,7 @@ Comparing individual elements of sorted subarrays until we reach end of one
### 步骤 4:当我们用完`L`或`M`中的元素时,请取剩余的元素并放入`A[p..r]`
### 步骤 4:当我们用完`L`或`M`中的元素时,请取剩余的元素并放入`A[p..r]`
```
// We exited the earlier loop because j < n2 doesn't hold
......@@ -618,8 +618,8 @@ int main() {
* * *
## 归并排序应用程序
## 归并排序应用
* 倒数问题
* 外部分类
* 外部排序
* 电子商务应用
\ No newline at end of file
......@@ -304,7 +304,7 @@ int main() {
* * *
## 复杂
## 复杂
**时间复杂度**
......@@ -333,7 +333,7 @@ int main() {
* * *
## 计算排序应用程序
## 计算排序应用
在以下情况下使用计数排序:
......
......@@ -341,7 +341,7 @@ int main() {
* * *
## 复杂
## 复杂
由于基数排序是一种非比较算法,因此它比比较排序算法具有优势。
......
......@@ -8,7 +8,7 @@
创建了几个存储桶。 每个存储桶都填充有特定范围的元素。 存储桶中的元素使用任何其他算法进行排序。 最后,收集存储桶中的元素以获取排序后的数组。
分类的过程可以理解为**,分散收集**方法。 首先将元素分散到存储桶中,然后对存储桶的元素进行排序。 最后,元素按顺序收集。
排序的过程可以理解为**,分散收集**方法。 首先将元素分散到存储桶中,然后对存储桶的元素进行排序。 最后,元素按顺序收集。
![Bucket Sort Working](img/5205190afeb1f464bd5a69ea2e7c63c1.png "Working of bucket sort")
......@@ -18,7 +18,7 @@ Working of Bucket Sort
* * *
## 桶分类如何工作?
## 桶排序如何工作?
1. 假设输入数组为:
......@@ -510,7 +510,7 @@ int main(void) {
* * *
## 复杂
## 复杂
* **最坏情况的复杂度**`O(n^2)`
当数组中有近距离的元素时,它们很可能放在同一存储桶中。 这可能会导致某些存储桶中的元素数量比其他存储桶更多。
......@@ -518,14 +518,14 @@ int main(void) {
当元素的顺序相反时,复杂度将变得更加糟糕。 如果使用插入排序对存储桶中的元素进行排序,则时间复杂度变为`O(n^2)`
* **最佳情况复杂度**`O(n+k)`
当元素在桶中均匀分布且每个桶中元素数量几乎相等时,会发生这种情况。
如果存储桶中的元素已经被分类,那么复杂度就会变得更好。
如果使用插入排序对存储桶中的元素进行排序,则最佳情况下的总体复杂度将是线性的,即。`O(n+k)``O(n)`是制造存储桶的复杂度,`O(k)`是使用在最佳情况下具有线性时间复杂度的算法对存储桶的元素进行分类的复杂度。
如果存储桶中的元素已经被排序,那么复杂度就会变得更好。
如果使用插入排序对存储桶中的元素进行排序,则最佳情况下的总体复杂度将是线性的,即。`O(n+k)``O(n)`是制造存储桶的复杂度,`O(k)`是使用在最佳情况下具有线性时间复杂度的算法对存储桶的元素进行排序的复杂度。
* **平均情况复杂度**`O(n)`
当元素在数组中随机分布时发生。 即使元素分布不均匀,存储桶排序也会在线性时间内运行。 直到铲斗大小的平方和在元素总数中呈线性关系时,它才成立。
* * *
## 桶分类应用
## 桶排序应用
在以下情况下使用存储桶排序:
......
......@@ -90,7 +90,7 @@ Max Heap and Min Heap
* * *
## 如何“堆肥”一棵树
## 如何对一棵树“建堆”
从完全二叉树开始,我们可以通过在堆的所有非叶元素上运行一个称为`heapify`的函数,将其修改为最大堆。
......@@ -491,8 +491,8 @@ Swap, Remove, and Heapify
* * *
## 堆分类应用
## 堆排序应用
涉及安全性的系统和嵌入式系统(例如 Linux Kernel)使用堆排序,因为堆排序的运行时间上限为`O(n log n)`,辅助存储的上限为`O(1)`上限。
尽管即使在最坏的情况下,堆排序也具有`O(n log n)`时间复杂度,但它没有更多的应用程序(与其他排序算法(如快速排序,归并排序)相比)。 但是,如果我们要从项目列表中提取最小(或最大)的数据,而无需保持其余项目按排序顺序的开销,则可以有效地使用其基础数据结构堆。 例如,优先队列。
\ No newline at end of file
尽管即使在最坏的情况下,堆排序也具有`O(n log n)`时间复杂度,但它没有更多的应用(与其他排序算法(如快速排序,归并排序)相比)。 但是,如果我们要从项目列表中提取最小(或最大)的数据,而无需保持其余项目按排序顺序的开销,则可以有效地使用其基础数据结构堆。 例如,优先队列。
\ No newline at end of file
......@@ -234,7 +234,7 @@ int main() {
* * *
## 复杂
## 复杂
Shell 排序是一种不稳定的排序算法,因为该算法不会检查间隔之间的元素。
......@@ -257,7 +257,7 @@ Shell 排序是一种不稳定的排序算法,因为该算法不会检查间
* * *
## 壳牌分类应用
## Shell 排序应用
在以下情况下使用 Shell 排序:
......
# 线性搜
# 线性搜
> 原文: [https://www.programiz.com/dsa/linear-search](https://www.programiz.com/dsa/linear-search)
......
......@@ -12,7 +12,7 @@
* * *
## 二分搜索工作
## 二分搜索原理
二分搜索算法可以通过以下两种方式实现。
......
......@@ -32,7 +32,7 @@
* * *
## 示例-贪婪方法
## 贪婪方法示例
```
Problem: You have to make a change of an amount using the smallest possible number of coins.
......@@ -69,5 +69,5 @@ Available coins:
* [Prim 的最小生成树算法](/dsa/prim-algorithm)
* [Kruskal 的最小生成树算法](/dsa/kruskal-algorithm)
* [Dijkstra 的最小生成树算法](/dsa/dijkstra-algorithm)
* [夫曼编码](/dsa/huffman-coding)
* [夫曼编码](/dsa/huffman-coding)
* [Ford-Fulkerson 算法](/dsa/ford-fulkerson-algorithm)
\ No newline at end of file
# 福特-福克森算法
# Ford-Fulkerson 算法
> 原文: [https://www.programiz.com/dsa/ford-fulkerson-algorithm](https://www.programiz.com/dsa/ford-fulkerson-algorithm)
......@@ -20,11 +20,11 @@ Flow network graph
## 使用的术语
### 增路径
### 增广路径
它是流网络中可用的路径。
### 残差
### 剩余
它表示具有其他可能流量的网络流。
......@@ -34,7 +34,7 @@ Flow network graph
* * *
## 福特-富克森算法如何工作?
## Ford-Fulkerson 算法如何工作?
该算法如下:
......@@ -48,7 +48,7 @@ Flow network graph
* * *
## 福特福克森的例子
## Ford-Fulkerson 的例子
开始时所有边的流为 0。
......@@ -462,7 +462,7 @@ int main() {
* * *
## 福特福克森应用
## Ford-Fulkerson 应用
* 输水管道
* 二分匹配问题
......
# Dijkstra 算法
# Dijkstra 算法
> 原文: [https://www.programiz.com/dsa/dijkstra-algorithm](https://www.programiz.com/dsa/dijkstra-algorithm)
#### Dijkstra 算法使我们能够找到图形中任意两个顶点之间的最短路径。
#### Dijkstra 算法使我们能够找到图形中任意两个顶点之间的最短路径。
它与最小生成树不同,因为两个顶点之间的最短距离可能不包括图形的所有顶点。
......@@ -10,7 +10,7 @@
## Dijkstra 算法的工作原理
Dijkstra 算法的工作原理是,顶点`A``D`之间的最短路径`A -> D`的任何子路径`B -> D`也是顶点`B``D`之间的最短路径。
Dijkstra 算法的工作原理是,顶点`A``D`之间的最短路径`A -> D`的任何子路径`B -> D`也是顶点`B``D`之间的最短路径。
![shortest subpath property is used by dijkstra's algorithm](img/9498777e7e23c844e777073185804323.png "Subpaths - Dijkstra's Algorithm")
......@@ -578,7 +578,7 @@ void RemoveEdge(vector<Edge*>& edges, Edge* edge) {
* * *
## Dijkstra 算法复杂度
## Dijkstra 算法复杂度
时间复杂度:`O(E Log V)`
......@@ -588,7 +588,7 @@ void RemoveEdge(vector<Edge*>& edges, Edge* edge) {
* * *
## Dijkstra 算法应用
## Dijkstra 算法应用
* 寻找最短路径
* 社交网络中的应用
......
# 克鲁斯卡尔算法
# Kruskal 算法
> 原文: [https://www.programiz.com/dsa/kruskal-algorithm](https://www.programiz.com/dsa/kruskal-algorithm)
#### 在本教程中,您将学习 Kruskal 算法如何工作。 此外,您还将找到 C,C++ ,Java 和 Python 中 Kruskal 算法的工作示例。
#### 在本教程中,您将学习 Kruskal 算法如何工作。 此外,您还将找到 C,C++ ,Java 和 Python 中 Kruskal 算法的工作示例。
Kruskal 算法是一种[最小生成树](/dsa/spanning-tree-and-minimum-spanning-tree#minimum-spanning)算法,该算法将图形作为输入,并找到该图形的边子集,
......@@ -545,13 +545,13 @@ int main() {
* * *
## 克鲁斯卡尔算法的复杂度
## Kruskal 算法的复杂度
Kruskal 算法的时间复杂度为:`O(E log E)`
* * *
## 克鲁斯卡尔算法的应用
## Kruskal 算法的应用
* 为了布置电线
* 在计算机网络中(LAN 连接)
\ No newline at end of file
# 普里姆算法
# Prim 算法
> 原文: [https://www.programiz.com/dsa/prim-algorithm](https://www.programiz.com/dsa/prim-algorithm)
......@@ -65,7 +65,7 @@ Repeat until you have a spanning tree
* * *
## 普里姆算法伪代码
## Prim 算法伪代码
prim 算法的伪代码显示了我们如何创建两组顶点`U``V-U``U`包含已访问的顶点列表,而`V-U`包含尚未访问的顶点列表。 通过连接最小权重边,将顶点从集合`V-U`移到集合`U`
......@@ -375,9 +375,9 @@ int main() {
* * *
## 普里姆斯与克鲁斯卡尔算法
## Prim 与 Kruskal 算法
[Kruskal 算法](/dsa/kruskal-algorithm)是另一种流行的最小生成树算法,它使用不同的逻辑来查找图的 MST。 Kruskal 算法不是从顶点开始,而是对所有边从低权重到高边进行排序,并不断添加最低边,而忽略那些会产生循环的边。
[Kruskal 算法](/dsa/kruskal-algorithm)是另一种流行的最小生成树算法,它使用不同的逻辑来查找图的 MST。 Kruskal 算法不是从顶点开始,而是对所有边从低权重到高边进行排序,并不断添加最低边,而忽略那些会产生循环的边。
* * *
......
......@@ -10,7 +10,7 @@
* * *
## 夫曼编码的工作原理?
## 夫曼编码的工作原理?
假设下面的字符串要通过网络发送。
......
# 动态编程
\ No newline at end of file
# 动态规划
\ No newline at end of file
# 动态编程
# 动态规划
> 原文: [https://www.programiz.com/dsa/dynamic-programming](https://www.programiz.com/dsa/dynamic-programming)
#### 在本教程中,您将学习什么是动态编程。 此外,您还将发现动态编程和贪婪算法之间的比较,以解决问题。
#### 在本教程中,您将学习什么是动态规划。 此外,您还将发现动态规划和贪婪算法之间的比较,以解决问题。
动态编程是计算机编程中的一种技术,可帮助有效解决一类具有重叠子问题和[最佳子结构](https://en.wikipedia.org/wiki/Optimal_substructure)属性的问题。
动态规划是计算机编程中的一种技术,可帮助有效解决一类具有重叠子问题和[最佳子结构](https://en.wikipedia.org/wiki/Optimal_substructure)属性的问题。
这些问题涉及重复计算相同子问题的值以找到最佳解决方案。
* * *
## 动态编程实例
## 动态规划实例
以生成斐波那契数列为例。
......@@ -24,13 +24,13 @@ F(48) = F(47) + F(46)
```
注意,子问题如何重叠,我们需要计算`F(48)`才能计算`F(50)``F(49)`。 这正是动态编程大放异彩的算法。
注意,子问题如何重叠,我们需要计算`F(48)`才能计算`F(50)``F(49)`。 这正是动态规划大放异彩的算法。
* * *
## 动态编程的工作原理
## 动态规划的工作原理
动态编程通过存储子问题的结果来工作,以便在需要它们的解决方案时就可以使用它们,而我们无需重新计算它们。
动态规划通过存储子问题的结果来工作,以便在需要它们的解决方案时就可以使用它们,而我们无需重新计算它们。
这种存储子问题值的技术称为记忆。 通过将值保存在数组中,我们节省了计算遇到的子问题的时间。
......@@ -43,7 +43,7 @@ function fib(n)
```
通过备注进行动态编程是一种自顶向下的动态编程方法。 通过反转算法的工作方向,即从基本情况开始并朝解决方案努力,我们还可以自下而上地实现动态编程
通过备注进行动态规划是一种自顶向下的动态规划方法。 通过反转算法的工作方向,即从基本情况开始并朝解决方案努力,我们还可以自下而上地实现动态规划
```
function fib(n)
......@@ -61,13 +61,13 @@ function fib(n)
* * *
## 递归与动态编程
## 递归与动态规划
动态编程主要应用于递归算法。 这不是巧合,大多数优化问题都需要递归,并且将动态编程用于优化。
动态规划主要应用于递归算法。 这不是巧合,大多数优化问题都需要递归,并且将动态规划用于优化。
但是并非所有使用递归的问题都可以使用动态编程。 除非像斐波那契数列问题那样存在重叠的子问题,否则递归只能使用分治的方法来解决。
但是并非所有使用递归的问题都可以使用动态规划。 除非像斐波那契数列问题那样存在重叠的子问题,否则递归只能使用分治的方法来解决。
这就是为什么诸如归并排序的递归算法不能使用动态编程的原因,因为子问题不会以任何方式重叠。
这就是为什么诸如归并排序的递归算法不能使用动态规划的原因,因为子问题不会以任何方式重叠。
* * *
......@@ -77,4 +77,4 @@ function fib(n)
但是,贪婪算法会寻找局部最优解,或者换句话说,是贪婪的选择,以期找到全局最优解。 因此,贪婪的算法可能会做出一个猜测,即看起来当时是最优的,但代价很高,并且不能保证全局最优。
另一方面,动态编程会找到子问题的最佳解决方案,然后做出明智的选择,以合并那些子问题的结果以找到最佳解决方案。
\ No newline at end of file
另一方面,动态规划会找到子问题的最佳解决方案,然后做出明智的选择,以合并那些子问题的结果以找到最佳解决方案。
\ No newline at end of file
......@@ -10,7 +10,7 @@ Floyd-Warshall 算法是一种用于找到加权图中所有顶点对之间的
Floyd-Warhshall 算法也称为 Floyd 算法,Roy-Floyd 算法,Roy-Warshall 算法或 WFI 算法。
该算法遵循[动态编程](/dsa/dynamic-programming)方法来找到最短路径。
该算法遵循[动态规划](/dsa/dynamic-programming)方法来找到最短路径。
* * *
......
......@@ -31,13 +31,13 @@ S2 = {A, C, D, B, A, C}
然后,常见的子序列是`{B, C}, {C, D, A, C}, {D, A, C}, {A, A, C}, {A, C}, {C, D}, ...`
在这些子序列中,`{C, D, A, C}`是最长的公共子序列。 我们将使用动态编程来找到这个最长的公共子序列。
在这些子序列中,`{C, D, A, C}`是最长的公共子序列。 我们将使用动态规划来找到这个最长的公共子序列。
在继续进行之前,如果您还不了解动态编程,请进行[动态编程](/dsa/dynamic-programming)
在继续进行之前,如果您还不了解动态规划,请进行[动态规划](/dsa/dynamic-programming)
* * *
## 使用动态编程查找 LCS
## 使用动态规划查找 LCS
让我们采取两个顺序:
......@@ -109,9 +109,9 @@ LCS
* * *
**在解决 LCS 问题时,动态编程算法比递归算法效率如何?**
**在解决 LCS 问题时,动态规划算法比递归算法效率如何?**
动态编程的方法减少了函数调用的次数。 它存储每个函数调用的结果,以便可以在以后的调用中使用它,而无需冗余调用。
动态规划的方法减少了函数调用的次数。 它存储每个函数调用的结果,以便可以在以后的调用中使用它,而无需冗余调用。
在上述动态算法中,将从`X`的元素与`Y`的元素之间的每次比较获得的结果存储在表中,以便可以在将来的计算中使用。
......@@ -367,7 +367,7 @@ int main() {
* * *
## 最长的通用子序列应用
## 最长的公共子序列应用
1. 在压缩基因组重排数据中
2. 通过空中签名在手机中验证用户身份
\ No newline at end of file
......@@ -10,7 +10,7 @@
术语“回溯”表示如果当前解决方案不合适,则回溯并尝试其他解决方案。 因此,在此方法中使用了递归。
此方法用于解决具有多种解决方案的问题。 如果需要最佳解决方案,则必须进行[动态编程](/dsa/dynamic-programming)
此方法用于解决具有多种解决方案的问题。 如果需要最佳解决方案,则必须进行[动态规划](/dsa/dynamic-programming)
* * *
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册