update readme
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
# 字符串匹配算法 KMP
|
||||
|
||||
KMP于1977年被提出,全称 Knuth–Morris–Pratt 算法; 名字分别是:Donald Knuth(K), James H. Morris(M), Vaughan Pratt(P).
|
||||
|
||||
KMP算法是一种字符串匹配算法,可以在 O(n+m) 的时间复杂度内实现两个字符串的匹配。
|
||||
|
||||
|
||||
@@ -23,6 +23,13 @@ java 中扩容,每次扩容新增原先容量的 1/2
|
||||
这个就不介绍了。重点说下双向链表。
|
||||
|
||||
|
||||
### 链表 VS 数组
|
||||
|
||||
|
||||
* 查询: 数组 O(1), 内存连续, 有序时可以用二分查找;有界
|
||||
* 删除: 链表只需要移动指针 O(1) ,数组的话删除元素需要移动后续的元素 O(N)
|
||||
|
||||
|
||||
## 双向链表
|
||||
|
||||
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
|
||||
|
||||
@@ -49,3 +49,10 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-4
@@ -23,10 +23,12 @@
|
||||
|
||||
## [AVL树](3-平衡树AVL/README.md)
|
||||
|
||||
绝对的平衡二叉树;
|
||||
|
||||
|
||||
## [红黑树](9-红黑树%20R-B%20tree/红黑树.md)
|
||||
|
||||
弱平衡二叉树;使用广泛
|
||||
|
||||
|
||||
## [字典树trie](4-字典树Trie/README.md)
|
||||
@@ -50,10 +52,6 @@
|
||||
|
||||
|
||||
|
||||
## 赫夫曼编码 Huffman
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
# DFS 和 BFS
|
||||
# DFS 和 BFS 搜索算法
|
||||
|
||||
|
||||
> DFS用递归的形式,用到了栈结构,先进后出; BFS选取状态用队列的形式,先进先出。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+9
-6
@@ -9,12 +9,12 @@
|
||||
|
||||
### 应用场景
|
||||
|
||||
工业界有哪些应用场景
|
||||
工业界有哪些应用场景?
|
||||
|
||||
* 匹配,如打车中司乘匹配引擎,如何做到效率最优
|
||||
* 并行任务调度,一组任务,任务有优先级,如何合理安排任务调度,在最短时间内完成
|
||||
* 导航路径规划,在使用导航软件时,用户在选择一个开始地点和目的地之后导航软件会给出各种如路程最短,不走高速,时长最短等方案
|
||||
* 社区发现,在好友关系中,根据社区之间联系或紧密,利用图 louvain 算法或者其他算法对用户进行分群从而达到精准营销,个性化服务等
|
||||
* 并行任务调度: 一组任务,任务有优先级,如何合理安排任务调度,在最短时间内完成
|
||||
* 导航路径规划:在使用导航软件时,用户在选择一个开始地点和目的地之后导航软件会给出各种如路程最短,不走高速,时长最短等方案
|
||||
* 社区发现: 在好友关系中,根据社区之间联系或紧密,利用图 louvain 算法或者其他算法对用户进行分群从而达到精准营销,个性化服务等
|
||||
* 金融贷后催收:利用图算法找出符合条件的失联人的联系人,从而提高催收失联修复的覆盖率、有效联系率,助力不良资产的回收
|
||||
* 套汇
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
|
||||
#### 遍历
|
||||
|
||||
* 广度优先
|
||||
* 深度优先
|
||||
* 广度优先 BFS
|
||||
* 深度优先 DFS
|
||||
|
||||
Dijkstra
|
||||
A*
|
||||
@@ -67,3 +67,6 @@ https://www.jiqizhixin.com/articles/2019-05-16-14
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
# 最短路径
|
||||
|
||||
|
||||
Dijkstra(迪杰斯特拉)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+84
-54
@@ -3,21 +3,32 @@
|
||||
**排序的稳定性** 是指对于相等的元素,排序之后,任然保存2个元素的位置没有变,就是稳定的排序,反之就是不稳定排序。
|
||||
|
||||
|
||||
**交换排序算法**
|
||||
* 交换排序算法
|
||||
* 桶排序
|
||||
|
||||
### 交换排序算法
|
||||
|
||||
* 冒泡排序 :没轮确定一个最大的数排后面
|
||||
* 插入排序
|
||||
* 选择排序 :每轮选择最小的数排前面
|
||||
* 希尔排序
|
||||
* 快排 : 选最后一个作为pivot(基数), 将数据分为 左边小于 pivot, 右边大于 pivot
|
||||
* 归并排序 :
|
||||
* 堆排序
|
||||
* 快排 : 选最后一个作为pivot(基数), 将数据分为 左边小于 pivot, 右边大于 pivot; 分治递归, 二叉树的前序遍历思路
|
||||
* 归并排序 : 将无序的数组,分成2个子数组分别排序,然后再merge ; 分治递归, 二叉树的后续遍历思路
|
||||
* 插入排序 :
|
||||
* 希尔排序 :
|
||||
* 堆排序 :
|
||||
|
||||
**线性排序算法**
|
||||
|
||||
### 线性排序算法
|
||||
|
||||
* 桶排序
|
||||
|
||||
|
||||
### 小结
|
||||
|
||||
常见的排序算法都是比较排序,比较排序的时间复杂度通常为 O(n^2) 或 O(nlogn)
|
||||
但是如果带排序的数字有一些特俗性时,我们可以根据这来设计更加优化的排序算法。
|
||||
|
||||
|
||||
|
||||
# 交换排序算法
|
||||
|
||||
排序算法的复杂度由 `比较的次数` 和 `交换的次数` 一起决定。
|
||||
@@ -31,6 +42,8 @@
|
||||
在a【i,n】中最小的元素和 a[i]交换位置。空间复杂度O(1),时间复杂度 O(n^2)
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
### 冒泡排序
|
||||
|
||||
@@ -40,50 +53,41 @@
|
||||
|
||||
这样,即使是排好序的拿冒泡排序排序,比较的时间复杂度O(n^2)
|
||||
|
||||
|
||||
|
||||
|
||||
### 插入排序
|
||||
|
||||
1. 第一个元素算作已经排好
|
||||
2. 取下一个元素,从已经排好的序列元素中,从后向前扫描
|
||||
3. 如果排好序的元素大于 新元素,排好序的元素移到下一个位置
|
||||
4. 重复3,直到直到最后的插入位置
|
||||
5. 重复2
|
||||
|
||||
类似插入扑克牌的效果
|
||||
|
||||
最坏的情况: 待排序的是一个逆序排放的数组,这样导致每一轮都要移动元素;此时复杂度是是0(n^2)
|
||||
最好的情况: 待排序的是一已经顺序排放的数字,此时只需要做一轮比较就够了 0(n)。因此可以看到,**对大部分数据已经有序这样的数组排序,使用`插入排序`非常有优势**
|
||||
|
||||
空间复杂度O(1)
|
||||
|
||||
|
||||
### 希尔排序
|
||||
|
||||
递减增量排序算法,对`插入排序`的改进,实质是分组插入排序,又叫`缩小增量排序`
|
||||
|
||||
1. 先将待排数列分割成若干子序列(增量为m)
|
||||
2. 对每个子序列使用`插入排序`
|
||||
3. 减小增量,再排序
|
||||
4. 对全体元素做一次`插入排序`
|
||||
|
||||
`希尔排序`提升排序的奥秘就在于`数据元素越有序,使用插入排序效率越高`
|
||||
|
||||

|
||||
|
||||
|
||||
### 快速排序
|
||||
|
||||
|
||||
时间复杂度 平均复杂度 O(n * logn) , 最坏 O(n^2)
|
||||
空间复杂度
|
||||
快速排序是对冒泡排序的改进,划分交换排序。
|
||||
|
||||
|
||||
递归一次,pivot 左边都比它小,右边都比它大。这是递归,分治的思想。
|
||||
|
||||
> 快速排序就是个二叉树的前序遍历,归并排序就是个二叉树的后序遍历
|
||||
> 快速排序就是个二叉树的前序遍历思路,归并排序就是个二叉树的后序遍历思路
|
||||
|
||||
|
||||
代码框架如下
|
||||
|
||||
```
|
||||
void quicksort(int *a, int left, int right){
|
||||
if (left<right){//加上这个,不然有死循环,造成堆栈溢出,这也是递归结束条件
|
||||
|
||||
int i = partion(a,left,right);//使得局部有序,i作为分隔
|
||||
quicksort(a,left,i-1);
|
||||
quicksort(a,i+1,right);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
对 A[p...r] :
|
||||
|
||||
0. 选择最后一个元素作为 pivot (基准)
|
||||
1. 分解:A[p..q-1] A[q+1..r],使得 A[p...q-1]< A[q] <A[q+1..r]
|
||||
2. 解决:递归调用 快排,,对子数组A[p..q-1],A[q+1..r]排序
|
||||
2. 解决:递归调用 快排,对子数组A[p..q-1],A[q+1..r]排序
|
||||
3. 合并(子问题相互独立的,因此用分治算法就可以了)
|
||||
|
||||
具体步骤:
|
||||
@@ -93,6 +97,7 @@
|
||||
3. 递归的,使用相同的方式,重排左右两边的子序列
|
||||
|
||||
扫描过程分2种:
|
||||
|
||||
1. 挖坑排序,2头向中间扫描,先从后向前找,再从前向后找。
|
||||
2. 单向扫描
|
||||
|
||||
@@ -139,12 +144,7 @@
|
||||
```
|
||||
|
||||
|
||||
|
||||
平均复杂度 O(n * logn)
|
||||
最坏 O(n^2)
|
||||
空间复杂度
|
||||
快速排序是对冒泡排序的改进,划分交换排序。
|
||||
|
||||

|
||||
|
||||
|
||||
### 归并排序merge
|
||||
@@ -176,6 +176,40 @@ void sort(int[] nums, int lo, int hi) {
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
### 插入排序
|
||||
|
||||
1. 第一个元素算作已经排好
|
||||
2. 取下一个元素,从已经排好的序列元素中,从后向前扫描
|
||||
3. 如果排好序的元素大于 新元素,排好序的元素移到下一个位置
|
||||
4. 重复3,直到直到最后的插入位置
|
||||
5. 重复2
|
||||
|
||||
类似插入扑克牌的效果
|
||||
|
||||
最坏的情况: 待排序的是一个逆序排放的数组,这样导致每一轮都要移动元素;此时复杂度是是0(n^2)
|
||||
最好的情况: 待排序的是一已经顺序排放的数字,此时只需要做一轮比较就够了 0(n)。因此可以看到,**对大部分数据已经有序这样的数组排序,使用`插入排序`非常有优势**
|
||||
|
||||
空间复杂度O(1)
|
||||
|
||||
|
||||
|
||||
|
||||
### 希尔排序
|
||||
|
||||
递减增量排序算法,对`插入排序`的改进,实质是分组插入排序,又叫`缩小增量排序`
|
||||
|
||||
1. 先将待排数列分割成若干子序列(增量为m)
|
||||
2. 对每个子序列使用`插入排序`
|
||||
3. 减小增量,再排序
|
||||
4. 对全体元素做一次`插入排序`
|
||||
|
||||
`希尔排序`提升排序的奥秘就在于`数据元素越有序,使用插入排序效率越高`
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
@@ -235,6 +269,10 @@ void sort(int[] nums, int lo, int hi) {
|
||||
推排序还可以用来求 top-K 大(小)的问题。
|
||||
|
||||
|
||||
|
||||
#排序动画演示
|
||||
|
||||
|
||||
接下来,我们看一组排序的动画,你看看能不能猜到他们使用了什么排序算法完成。
|
||||
|
||||

|
||||
@@ -255,7 +293,7 @@ void sort(int[] nums, int lo, int hi) {
|
||||
|
||||
# 线性排序算法
|
||||
|
||||
上面的算法都是基于比较的排序,时间复杂度最好也是 NlogN.而非基于比较的排序,可以突破NlogN的时间下限。当然,非比较的排序,也是需要有一些限定条件的。
|
||||
上面的算法都是基于比较的排序,时间复杂度最好也是 NlogN. 而非基于比较的排序,可以突破NlogN的时间下限。当然,非比较的排序,也是需要有一些限定条件的。
|
||||
|
||||
|
||||
### 桶排序 bucket sort
|
||||
@@ -266,14 +304,6 @@ void sort(int[] nums, int lo, int hi) {
|
||||
|
||||
|
||||
|
||||
# 小结
|
||||
|
||||
常见的排序算法都是比较排序,比较排序的时间复杂度通常为 O(n^2) 或 O(nlogn)
|
||||
但是如果带排序的数字有一些特俗性时,我们可以根据这来设计更加优化的排序算法。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
## 15个经典基础算法
|
||||
# 15个经典基础算法
|
||||
|
||||
|
||||
* A*寻路算法 :求解最短路径
|
||||
@@ -18,6 +17,6 @@
|
||||
* 快递选择SELECT
|
||||
|
||||
|
||||
### Dijkstra 最短路径算法
|
||||
|
||||
**Dijkstra** 是荷兰的计算机科学家,提出”信号量和PV原语“,"解决哲学家就餐问题",”死锁“也是它提出来的
|
||||
|
||||
|
||||
|
||||
@@ -163,20 +163,20 @@
|
||||
|
||||
## 15个经典基础算法
|
||||
|
||||
* Hash
|
||||
* 快速排序
|
||||
* [Hash](3%20Hash%20Table/README.md)
|
||||
* [快速排序](6%20Sort/README.md)
|
||||
* 快递选择SELECT
|
||||
* BFS/DFS (广度/深度优先遍历)
|
||||
* 红黑树 (一种自平衡的`二叉查找树`)
|
||||
* KMP 字符串匹配算法
|
||||
* DP (动态规划 dynamic programming)
|
||||
* [红黑树 (一种弱/自平衡的`二叉查找树`)](4%20Tree/9-红黑树%20R-B%20tree/红黑树.md)
|
||||
* [DP (动态规划 dynamic programming)](8%20Algorithms%20Analysis/动态规划.md)
|
||||
* [KMP 字符串匹配算法](1%20String/KMP.md)
|
||||
* A*寻路算法: 求解最短路径
|
||||
* Dijkstra:最短路径算法 (八卦下:Dijkstra是荷兰的计算机科学家,提出”信号量和PV原语“,"解决哲学家就餐问题",”死锁“也是它提出来的)
|
||||
* 遗传算法
|
||||
* `SPFA(shortest path faster algorithm)` 单元最短路径算法
|
||||
* 启发式搜索
|
||||
* 图像特征提取之 SIFT 算法
|
||||
* 遗传算法 `GA`
|
||||
* 图像特征提取之`SIFT` 算法
|
||||
* 傅立叶变换
|
||||
* SPFA(shortest path faster algorithm) 单元最短路径算法
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user