算法图解 笔记
第一章 算法简介
1. 二分查找
一般而言,对于包含n个元素的列表,用二分查找最多需要$ log_2n $步
2. 运行时间
线性时间:需要计算的次数和列表长度相同
3. 大O表示法
大O表示法指出了最糟情况下的运行时间
4. 一些常见的大O运行时间(从快到慢顺序):
O
(
l
o
g
2
n
)
O(log_2n)
O(log2n) :对数时间,二分查找
O
(
n
)
O(n)
O(n):线性时间,简单查找
O
(
n
∗
l
o
g
n
)
O(n*logn)
O(n∗logn):快速排序
O
(
n
2
)
O(n^2)
O(n2):选择排序
O
(
n
!
)
O(n!)
O(n!):旅行商问题
第二章 选择排序
1. 数组和链表操作的运行时间
- | 数组 | 链表 |
---|---|---|
读取 | O ( 1 ) O(1) O(1) | O ( n ) O(n) O(n) |
插入 | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) |
删除 | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) |
数组支持随机访问,链表只能顺序访问。
一种混合数据结构:链表数组
2.选择排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。(或者将每次排序后的最大(小)元素放进新数组)
平均复杂度:
O
(
N
2
)
O(N^2)
O(N2)
最佳时间复杂度:
O
(
N
2
)
O(N^2)
O(N2)
最差时间复杂度:
O
(
N
2
)
O(N^2)
O(N2)
空间复杂度:
O
(
1
)
O(1)
O(1)
稳定性:不稳定
第三章 递归
1. 递归函数
基线条件和递归条件
2. 栈、调用栈、递归调用栈
第四章 快速排序
1. 分治(D&C)
(1)找出简单的基线条件
(2)确定如何缩小问题的规模,使其符合基线条件
2. 快速排序
(1)选择基准值
(2)将数组分成两个子数组:小于基准值的元素和大于基准值的元素
(3)对两个子数组进行快速排序
快速排序的独特之处在于,其速度取决于选择的基准值。
最佳/平均运行时间:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
最差时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
第五章 散列表(hash table)
1. 散列表
应用:
(1)将散射表用于查找
(2)防止重复
(3)将散列表用作缓存
最优时间复杂度: O ( 1 ) O(1) O(1)
2. 冲突
处理冲突的方式很多,最简单的办法如下:如果两个键映射到了同一个位置,就在这个位置存储一个链表。但是当散列表某一位置的链表过长,散列表性能下降。
第六章 广度优先搜索
1. 广度优先搜索
可以解决两类问题:
第一类问题:从节点A出发,有前往节点B的路径吗?
第二类问题:从节点A出发,前往节点B的那条路径最短?
2. 用队列实现BFS伪代码:
1 procedure BFS(G, root) is
2 let Q be a queue
3 label root as explored
4 Q.enqueue(root)
5 while Q is not empty do
6 v := Q.dequeue()
7 if v is the goal then
8 return v
9 for all edges from v to w in G.adjacentEdges(v) do
10 if w is not labeled as explored then
11 label w as explored
12 w.parent := v
13 Q.enqueue(w)
第七章 狄克斯特拉算法
1. 狄克斯特拉算法——计算加权图中的最短路径
狄克斯特拉只适用于有向无环图。
(1) 找出"最便宜"的节点,即可在最短时间内前往的节点。
(2) 对于该节点的邻居,检查是否有前往它们的更短路径,如果有,就更新其开销。
(3) 重复这个过程,直到对图中的每个节点都这样做了。
(4) 计算最终路径。
2. 不能将狄克斯特拉用于包含负权边的图。
如果图中包含负权边,使用贝尔曼-福德算法。
3. 算法
A[还有要处理的节点]-->B[获取离起点最近的节点]
B-->C[更新其邻居的开销]
C-->D[如果有邻居的开销被更新,同时更新其父节点]
D-->E[将该节点标记为处理过]
E-->A
第八章 贪婪算法
1. 贪婪算法
每步都选择局部最优解,最终得到的就是全局最优解。
2. 背包问题
背包问题中,贪婪策略不能获得最优解。
3. 集合覆盖问题
4. NP完全问题
第九章 动态规划
1. 背包问题
动态规划先解决子问题,再逐步解决大问题。一般用二维网格记录子问题的状态,单元格中的值通常是要优化的值。只有子问题是离散的,并且不依赖其他子问题时,动态规划才管用。
2. 最长公共子串
3. 最长公共子序列
第十章 K近邻算法
- KNN用于分类和回归
- 提取特征
- 回归用于预测
##第十一章 其他算法介绍
1. 树
二叉查找树:对于每个节点,左子节点的值都比它小,而右子节点的值都比它大。平均运行时间:
O
(
l
o
g
n
)
O(logn)
O(logn),最糟运行时间
O
(
n
)
O(n)
O(n)。缺点是不能随机访问。
另外,可以了解红黑树、B树、堆、伸展树等。
2. 反向索引
常用于创建搜索引擎
3. 傅里叶变换
4. 并行算法
5. MapReduce
MapReduce是一种流行的分布式算法,基于映射函数和归并函数。
归并:将一个数组转换成一个元素。
6. 布隆过滤器和HyperLogLog
7. SHA(安全散列算法)
SHA是一个散列函数,它生成一个散列值——一个较短的字符串。用于创建散列表的散列函数根据字符串生成数组索引,而SHA根据字符串生成另一个字符串。
SHA可以用于比较文件、检查密码等。