auto commit

This commit is contained in:
CyC2018
2019-03-08 21:56:42 +08:00
parent ce05657a6c
commit 722b67a3c7
19 changed files with 67 additions and 56 deletions

View File

@ -48,7 +48,7 @@
### 1. 近似
N<sup>3</sup>/6-N<sup>2</sup>/2+N/3 ~ N<sup>3</sup>/6。使用 ~f(N) 来表示所有随着 N 的增大除以 f(N) 的结果趋近于 1 的函数。
N<sup>3</sup>/6-N<sup>2</sup>/2+N/3 \~ N<sup>3</sup>/6。使用 \~f(N) 来表示所有随着 N 的增大除以 f(N) 的结果趋近于 1 的函数。
### 2. 增长数量级
@ -96,7 +96,7 @@ public interface ThreeSum {
### 1. ThreeSumSlow
该算法的内循环为 `if (nums[i] + nums[j] + nums[k] == 0)` 语句,总共执行的次数为 N(N-1)(N-2) = N<sup>3</sup>/6-N<sup>2</sup>/2+N/3因此它的近似执行次数为 ~N<sup>3</sup>/6增长数量级为 O(N<sup>3</sup>)。
该算法的内循环为 `if (nums[i] + nums[j] + nums[k] == 0)` 语句,总共执行的次数为 N(N-1)(N-2) = N<sup>3</sup>/6-N<sup>2</sup>/2+N/3因此它的近似执行次数为 \~N<sup>3</sup>/6增长数量级为 O(N<sup>3</sup>)。
```java
public class ThreeSumSlow implements ThreeSum {
@ -206,9 +206,9 @@ public class ThreeSumTwoPointer implements ThreeSum {
## 倍率实验
如果 T(N) ~ aN<sup>b</sup>logN那么 T(2N)/T(N) ~ 2<sup>b</sup>
如果 T(N) \~ aN<sup>b</sup>logN那么 T(2N)/T(N) \~ 2<sup>b</sup>
例如对于暴力的 ThreeSum 算法,近似时间为 ~N<sup>3</sup>/6。进行如下实验多次运行该算法每次取的 N 值为前一次的两倍,统计每次执行的时间,并统计本次运行时间与前一次运行时间的比值,得到如下结果:
例如对于暴力的 ThreeSum 算法,近似时间为 \~N<sup>3</sup>/6。进行如下实验多次运行该算法每次取的 N 值为前一次的两倍,统计每次执行的时间,并统计本次运行时间与前一次运行时间的比值,得到如下结果:
| N | Time(ms) | Ratio |
| :---: | :---: | :---: |
@ -219,7 +219,7 @@ public class ThreeSumTwoPointer implements ThreeSum {
| 8000 | 33575 | 8.2 |
| 16000 | 268909 | 8.0 |
可以看到T(2N)/T(N) ~ 2<sup>3</sup>,因此可以确定 T(N) ~ aN<sup>3</sup>logN。
可以看到T(2N)/T(N) \~ 2<sup>3</sup>,因此可以确定 T(N) \~ aN<sup>3</sup>logN。
```java
public class RatioTest {
@ -291,7 +291,7 @@ public abstract class Sort<T extends Comparable<T>> {
选择出数组中的最小元素,将它与数组的第一个元素交换位置。再从剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置。不断进行这样的操作,直到将整个数组排序。
选择排序需要 ~N<sup>2</sup>/2 次比较和 ~N 次交换,它的运行时间与输入无关,这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作。
选择排序需要 \~N<sup>2</sup>/2 次比较和 \~N 次交换,它的运行时间与输入无关,这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作。
<div align="center"> <img src="pics/21550397584141.gif"/> </div><br>
@ -350,8 +350,8 @@ public class Bubble<T extends Comparable<T>> extends Sort<T> {
插入排序的复杂度取决于数组的初始顺序,如果数组已经部分有序了,逆序较少,那么插入排序会很快。
- 平均情况下插入排序需要 ~N<sup>2</sup>/4 比较以及 ~N<sup>2</sup>/4 次交换;
- 最坏的情况下需要 ~N<sup>2</sup>/2 比较以及 ~N<sup>2</sup>/2 次交换,最坏的情况是数组是倒序的;
- 平均情况下插入排序需要 \~N<sup>2</sup>/4 比较以及 \~N<sup>2</sup>/4 次交换;
- 最坏的情况下需要 \~N<sup>2</sup>/2 比较以及 \~N<sup>2</sup>/2 次交换,最坏的情况是数组是倒序的;
- 最好的情况下需要 N-1 次比较和 0 次交换,最好的情况就是数组已经有序了。
以下演示了在一轮循环中,将元素 2 插入到左侧已经排序的数组中。
@ -804,14 +804,14 @@ public class HeapSort<T extends Comparable<T>> extends Sort<T> {
| :---: | :---: |:---: | :---: | :---: |
| 选择排序 | × | N<sup>2</sup> | 1 | |
| 冒泡排序 | √ | N<sup>2</sup> | 1 | |
| 插入排序 | √ | N ~ N<sup>2</sup> | 1 | 时间复杂度和初始顺序有关 |
| 插入排序 | √ | N \~ N<sup>2</sup> | 1 | 时间复杂度和初始顺序有关 |
| 希尔排序 | × | N 的若干倍乘于递增序列的长度 | 1 | 改进版插入排序 |
| 快速排序 | × | NlogN | logN | |
| 三向切分快速排序 | × | N ~ NlogN | logN | 适用于有大量重复主键|
| 三向切分快速排序 | × | N \~ NlogN | logN | 适用于有大量重复主键|
| 归并排序 | √ | NlogN | N | |
| 堆排序 | × | NlogN | 1 | 无法利用局部性原理|
快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 ~cNlogN这里的 c 比其它线性对数级别的排序算法都要小。
快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 \~cNlogN这里的 c 比其它线性对数级别的排序算法都要小。
使用三向切分快速排序,实际应用中可能出现的某些分布的输入能够达到线性级别,而其它排序算法仍然需要线性对数时间。
@ -2040,7 +2040,7 @@ public class Transaction {
查找需要分两步,首先查找 Key 所在的链表,然后在链表中顺序查找。
对于 N 个键M 条链表 (N>M),如果哈希函数能够满足均匀性的条件,每条链表的大小趋向于 N/M因此未命中的查找和插入操作所需要的比较次数为 ~N/M。
对于 N 个键M 条链表 (N>M),如果哈希函数能够满足均匀性的条件,每条链表的大小趋向于 N/M因此未命中的查找和插入操作所需要的比较次数为 \~N/M。
<div align="center"> <img src="pics/9_200.png"/> </div><br>
@ -2149,7 +2149,7 @@ public void delete(Key key) {
#### 3.5 调整数组大小
线性探测法的成本取决于连续条目的长度,连续条目也叫聚簇。当聚簇很长时,在查找和插入时也需要进行很多次探测。例如下图中 2~5 位置就是一个聚簇。
线性探测法的成本取决于连续条目的长度,连续条目也叫聚簇。当聚簇很长时,在查找和插入时也需要进行很多次探测。例如下图中 2\~5 位置就是一个聚簇。
<div align="center"> <img src="pics/11_200.png"/> </div><br>