auto commit
50
notes/算法.md
|
@ -91,11 +91,15 @@
|
|||
|
||||
## 1. 函数转换
|
||||
|
||||
指数函数可以转换为线性函数,从而在函数图像上显示的更直观。
|
||||
指数函数可以转换为线性函数,从而在函数图像上显示的更直观。例如
|
||||
|
||||
<div align="center"> <img src="https://latex.codecogs.com/gif.latex?T(N)=aN^3"/> 转换为 <img src="https://latex.codecogs.com/gif.latex?lg(T(N))=3lgN+lga"/> </div><br>
|
||||
<div align="center"> <div align="center"><img src="https://latex.codecogs.com/gif.latex?T(N)=aN^3"/></div> <br> </div><br>
|
||||
|
||||
<div align="center"> <img src="../pics//5510045a-8f32-487f-a756-463e51a6dab0.png"/> </div><br>
|
||||
可以在其两端同时取对数,得到:
|
||||
|
||||
<div align="center"> <div align="center"><img src="https://latex.codecogs.com/gif.latex?lg(T(N))=3lgN+lga"/></div> <br> </div><br>
|
||||
|
||||
<div align="center"> <img src="../pics//0ed83061-9c1e-4df3-b15b-69aad5bfe9b8.png" width="800"/> </div><br>
|
||||
|
||||
## 2. 数学模型
|
||||
|
||||
|
@ -103,13 +107,13 @@
|
|||
|
||||
使用 \~f(N) 来表示所有随着 N 的增大除以 f(N) 的结果趋近于 1 的函数 , 例如 N<sup>3</sup>/6-N<sup>2</sup>/2+N/3 \~ N<sup>3</sup>/6。
|
||||
|
||||
<div align="center"> <img src="../pics//ca3a793e-06e5-4ff3-b28e-a9c20540d164.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//8f1e2db5-a59b-4633-8b61-6b8b9505b8ea.png" width="600"/> </div><br>
|
||||
|
||||
**增长数量级**
|
||||
|
||||
增长数量级将算法与它的实现隔离开来,一个算法的增长数量级为 N<sup>3</sup> 与它是否用 Java 实现,是否运行于特定计算机上无关。
|
||||
|
||||
<div align="center"> <img src="../pics//1ea4dc9a-c4dd-46b5-bb11-49f98d57ded1.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//521969c9-71f6-44a5-9c78-118530e5c135.png" width="600"/> </div><br>
|
||||
|
||||
**内循环**
|
||||
|
||||
|
@ -121,7 +125,8 @@
|
|||
|
||||
## 3. ThreeSum
|
||||
|
||||
ThreeSum 程序用于统计一个数组中三元组的和为 0 的数量。
|
||||
ThreeSum 用于统计一个数组中三元组的和为 0 的数量。
|
||||
|
||||
|
||||
```java
|
||||
public class ThreeSum {
|
||||
|
@ -142,7 +147,7 @@ public class ThreeSum {
|
|||
}
|
||||
```
|
||||
|
||||
该程序的内循环为 if (a[i] + a[j] + a[k] == 0) 语句,总共执行的次数为 N<sup>3</sup>/6 - N<sup>2</sup>/2 + N/3,因此它的近似执行次数为 \~N<sup>3</sup>/6,增长数量级为 N<sup>3</sup>。
|
||||
该算法的内循环为`if (a[i] + a[j] + a[k] == 0)`语句,总共执行的次数为 N(N-1)(N-2) = N<sup>3</sup>/6 - N<sup>2</sup>/2 + N/3,因此它的近似执行次数为 \~N<sup>3</sup>/6,增长数量级为 N<sup>3</sup>。
|
||||
|
||||
**改进**
|
||||
|
||||
|
@ -159,7 +164,7 @@ public class ThreeSumFast {
|
|||
for (int i = 0; i < N; i++) {
|
||||
for (int j = i + 1; j < N; j++) {
|
||||
// rank() 方法返回元素在数组中的下标,如果元素不存在,这里会返回 -1。
|
||||
// 应该注意这里的下标必须大于 j,这样就不会重复统计了。
|
||||
// 应该注意这里的下标必须大于 j,否则会重复统计。
|
||||
if (BinarySearch.rank(-a[i] - a[j], a) > j) {
|
||||
cnt++;
|
||||
}
|
||||
|
@ -172,11 +177,13 @@ public class ThreeSumFast {
|
|||
|
||||
## 4. 倍率实验
|
||||
|
||||
如果 T(N) \~ aN<sup>b</sup>lgN,那么 T(2N)/T(N) \~ 2<sup>b</sup>,例如对于暴力方法的 ThreeSum 算法,近似时间为 \~N<sup>3</sup>/6,对它进行倍率实验得到如下结果:
|
||||
如果 T(N) \~ aN<sup>b</sup>lgN,那么 T(2N)/T(N) \~ 2<sup>b</sup>。
|
||||
|
||||
<div align="center"> <img src="../pics//6f5ed46f-86d7-4852-a34f-c1cf1b6343a0.png"/> </div><br>
|
||||
例如对于暴力方法的 ThreeSum 算法,近似时间为 \~N<sup>3</sup>/6。进行如下实验:多次运行该算法,每次取的 N 值为前一次的两倍,统计每次执行的时间,并统计本次运行时间与前一次运行时间的比值,得到如下结果:
|
||||
|
||||
可见 T(2N)/T(N)\~2<sup>3</sup>,也就是 b 为 3。
|
||||
<div align="center"> <img src="../pics//cc3d855a-4281-445b-8f83-8f855458de19.png"/> </div><br>
|
||||
|
||||
可以看到,T(2N)/T(N)\~2<sup>3</sup>,因此可以确定 T(N) \~ aN<sup>2</sup>lgN。
|
||||
|
||||
## 5. 注意事项
|
||||
|
||||
|
@ -204,6 +211,10 @@ public class ThreeSumFast {
|
|||
|
||||
## 1. 栈
|
||||
|
||||
first-in-last-out(FILO)
|
||||
|
||||
<div align="center"> <img src="../pics//1c237399-e322-4930-b5b4-a582b1ad8bda.png" width="300"/> </div><br>
|
||||
|
||||
**数组实现**
|
||||
|
||||
```java
|
||||
|
@ -312,6 +323,11 @@ public class Stack<Item> {
|
|||
```
|
||||
## 2. 队列
|
||||
|
||||
first-in-first-out(FIFO)
|
||||
|
||||
<div align="center"> <img src="../pics//c64f91e2-f5a8-436b-8663-b8f3fba3e098.png" width="300"/> </div><br>
|
||||
|
||||
|
||||
下面是队列的链表实现,需要维护 first 和 last 节点指针,分别指向队首和队尾。
|
||||
|
||||
这里需要考虑让哪个指针指针链表头部节点,哪个指针指向链表尾部节点。因为出队列操作需要让队首元素的下一个元素成为队首,就需要容易获取下一个元素,而链表的头部节点的 next 指针指向下一个元素,因此让队首指针 first 指针链表的开头。
|
||||
|
@ -365,11 +381,11 @@ public class Queue<Item> {
|
|||
|
||||
用于解决动态连通性问题,能动态连接两个点,并且判断两个点是否连接。
|
||||
|
||||
<div align="center"> <img src="../pics//365e5a18-cf63-4b80-bb12-da6b650653f7.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//1dc67ff6-d29b-4864-baac-fd6b23f9b2ac.png" width="200"/> </div><br>
|
||||
|
||||
**API**
|
||||
|
||||
<div align="center"> <img src="../pics//f60c2116-fd19-4431-a57c-102fcc41ebd9.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//0e6cf8bd-b84e-4b3c-b79d-40d7dd54e120.png" width="600"/> </div><br>
|
||||
|
||||
**基本数据结构**
|
||||
|
||||
|
@ -416,7 +432,7 @@ public class UF {
|
|||
|
||||
在 union 时只将触点的 id 值指向另一个触点 id 值,不直接用 id 来存储所属的连通分量。这样就构成一个倒置的树形结构,根节点需要指向自己。在进行查找一个节点所属的连通分量时,要一直向上查找直到根节点,并使用根节点的 id 值作为本连通分量的 id 值。
|
||||
|
||||
<div align="center"> <img src="../pics//81a75fed-5c1d-4e4c-af4a-4c38c2a48927.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//e1cd89d1-8973-41d0-8ea9-940d94c314d9.jpg" width="500"/> </div><br>
|
||||
|
||||
```java
|
||||
public int find(int p) {
|
||||
|
@ -434,7 +450,7 @@ public class UF {
|
|||
|
||||
这种方法可以快速进行 union 操作,但是 find 操作和树高成正比,最坏的情况下树的高度为触点的数目。
|
||||
|
||||
<div align="center"> <img src="../pics//70a09383-f432-4b0f-ba42-b5b30d104f0b.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//83575315-20b5-44a6-bf58-94460a141ffa.jpg" width="400"/> </div><br>
|
||||
|
||||
## 3. 加权 quick-union 算法
|
||||
|
||||
|
@ -442,7 +458,7 @@ public class UF {
|
|||
|
||||
理论研究证明,加权 quick-union 算法构造的树深度最多不超过 lgN。
|
||||
|
||||
<div align="center"> <img src="../pics//b0d94736-e157-4886-aff2-c303735b0a24.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//9a30b932-f69f-40a1-9564-a1354ff8cf29.jpg" width="400"/> </div><br>
|
||||
|
||||
```java
|
||||
public class WeightedQuickUnionUF {
|
||||
|
@ -489,7 +505,7 @@ public class WeightedQuickUnionUF {
|
|||
|
||||
## 5. 各种 union-find 算法的比较
|
||||
|
||||
<div align="center"> <img src="../pics//2b6037b2-ec69-4235-ad0e-886fa320d645.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//c11f5e3a-7a28-4db7-87b1-29ba1a2f2d72.jpg" width="600"/> </div><br>
|
||||
|
||||
# 排序
|
||||
|
||||
|
|
BIN
pics/0e6cf8bd-b84e-4b3c-b79d-40d7dd54e120.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
pics/0ed83061-9c1e-4df3-b15b-69aad5bfe9b8.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
pics/1c237399-e322-4930-b5b4-a582b1ad8bda.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
pics/1dc67ff6-d29b-4864-baac-fd6b23f9b2ac.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
pics/521969c9-71f6-44a5-9c78-118530e5c135.png
Normal file
After Width: | Height: | Size: 98 KiB |
BIN
pics/83575315-20b5-44a6-bf58-94460a141ffa.jpg
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
pics/8f1e2db5-a59b-4633-8b61-6b8b9505b8ea.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
pics/9a30b932-f69f-40a1-9564-a1354ff8cf29.jpg
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
pics/c11f5e3a-7a28-4db7-87b1-29ba1a2f2d72.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
pics/c64f91e2-f5a8-436b-8663-b8f3fba3e098.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
pics/cc3d855a-4281-445b-8f83-8f855458de19.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
pics/e1cd89d1-8973-41d0-8ea9-940d94c314d9.jpg
Normal file
After Width: | Height: | Size: 45 KiB |