这是对《算法图解》这本书的阅读总结,记录了《算法图解》一文的收获与感悟。。
第 01 章——算法简介
二分查找(有序序列)
大O表示法:表示最坏条件下,操作数的增速
常见大O运行时间(快到慢)
时间 | 说明 |
---|---|
O(logn) | 对数时间,二分查找 |
O(n) | 线性时间,简单查找 |
O(n*logn) | 快速排序 |
O(n^2) | 选择排序 |
O(n!) | 旅行商问题 |
实例
旅行商问题:前往n个地点,总旅程的最短路线。
第 02 章——选择排序
- 数组:内存连续,查询快,增删元素慢
- 链表:内存不连续,查询慢,增删元素快
- 链表数组:查询,增删元素介于数组和链表
- 选择排序:(1/2)n^2 #大O表示法忽略常数
实例
Facebook创建用户时,用链表数组:26个数组元素里面存放链表
第 03 章——递归
- 递归:调用自己
- 基准条件(base)
- 递归条件(recursive)
- 调用栈(call stack):先进后出,只有压入和弹出操作,内存占用可能很大
调用另外一个函数时,当前函数暂停,处于未完成状态
递归也调用了栈,当不为基准条件时,压入,为基准条件时,弹出
第 04 章——快速排序
- 分而治之(divide and conquer,D&C)
- 找出基准条件,尽量简单
2.不断分解问题(或缩小规模),直到符合基准条件
欧几里得算法
函数式编程
快速排序
- 选择一个元素,作为基准值(pivot)
- 按<、>基准值,进行分区(partitioning)
- 对<、>基准值得子数组,进行快速排序,最后合并。
- 最糟糕情况:O(n^2)
- 平均情况(最佳情况):O(n log n)
def quicksort ( array ) :
if len( array ) < 2 :
return array
else :
pivot = array[0]
less = [i for i in array[1: ] if i <= pivot ]
greater = [i for i in array[i: ] if i > pivot ]
return quicksort( less ) + [pivot] +quicksort( greater )
归纳证明
合并排序(merge sort)
最糟糕情况:O(n log n)
最佳情况(平均情况)
大O时间表示法:O(n) = C * n
常量C:算法所需的固定时间
第 05 章——散列表
散列函数:将输入映射为数字(作为数组的索引)
- 将同样的输入映射到相同的索引
- 尽量将不同的输入映射到不同的索引
- 如果映射到同一个索引上,就在这个位置创建一个存储链表
- 不超过数组长度,只返回有效的索引
散列表(hashmap):也叫,字典,映射,关联数组,通过散列函数,把value值存放到对应数组索引
-
平均情况下:O( 1)
-
最糟糕情况下:O( n )
-
较低的装填因子:包含的元素/总位置数(通常为3/4),大于就调整长度为原来的1倍
-
良好的散列函数:SHA函数
作用
- 用于查找、删除、插入:DNS解析、DNS resolution(网站映射到ip地址)
- 防止重复:投票
- 用于缓存:保存用户数据,下次直接返回数据
第 06 章——广度优先搜索
- 图:由节点(node)和边(edge)组成。
- 邻居:相连的俩个节点、
- 有向图(directed graph):有方向
- 无向图(undirected graph):无方向
广度优先搜索(breadth-first search,BFS)
用图来建立问题模型
使用广度优先搜索(先一度关系,再二度关系)
使用队列添加顺序检查(检查过的人不必再检查
运行时间:O( V + E ) , V是顶点数(vertice),E为边数
- 队列(queue):先进先出(First in First out,FIFO)
- 拓扑排序:A依赖与B,A必须在B任务后面。
作用:解决最短路径问题:shortest-path problem
- 从A出发,是否有路径到B
- 从A出发,到B那条路径最短
第 07 章——狄克斯特拉算法
- 加权图(weighted graph):每条边都有固定关联数字(权重),有权重的图。
- 非加权图(unweighted graph):没有权重的图
- 负权边:权重为负
狄克斯特拉算法(Dijkstra‘s algorithm):找出最快的路径
- 找出最便宜的节点
- 更新该节点邻居的开销(权重)
- 重复这个步骤,直到所有节点都做了
- 计算最终路径
只适合有向无环图(directed acyclic graph,DAG)
有负权边则不可使用(可使用,贝尔曼-福德算法)
第 08 章——贪婪算法
- 贪婪算法:每步都选择局部最优解。
- 只能接近最优解,有时候并不是最优解
集合覆盖问题
- 幂集(power set):每个可能的子集。2^n个
- 并集:集合合并
- 交集:都有的元素集合
- 差集:除去另外一个集合有的元素
近似算法(approximation algrithm):解决NP完全问题
- 速度有多快
- 得到近似解与最优解的接近程度
NP完全问题:为了解决集合覆盖问题,必须计算每个可能的集合 O( n! )
- 必须考虑各种情况
- 阶乘函数(factorial function)
第 09 章——动态规划
-
动态规划:将问题分成小问题,并先着手解决这些小问题。
-
最长子公共字串
-
最长公共子序列
第 10 章——K最近邻算法
K最近邻算法(K-nearest neighbours,KNN):通过最接近的对象,判断本物体是什么?(或者喜欢什么)
- 毕达哥拉斯公式:(计算俩点距离)a2+b2=c^2
- 特征抽取:选出紧密相关,不偏不倚的特征,进行对比判断。(转换为数字)
- 余弦相识度(cosine similarity)
- 分类:是编组
- 回归(regression):预测结果
应用
-
分类系统
-
推荐系统
-
机器学习:
- OCR,光学字符识别(optical character recognition):拍摄印刷页面的照片,识别出其中的文字。
- 训练(training):浏览大量的数字图像,提取数字特征(曲线,点,线段)
- 遇到新图像时,提取该特征,找出最近的邻居是谁
-
垃圾邮件过滤器:
朴素贝叶斯分类器(Naive Bayes classifier):对特定数据进行训练,然后判断是垃圾邮件的概率。
第 11 章——接下来如何做
二叉查找树(binary search tree):
每个节点:左子节点比它小,右子节点比它大。
- 先检查根节点。
优点:
- 效率,跟二分查找一致。
- 删除和插入的效率要快。
缺点:
-
不能随机访问
-
红黑树:处于平衡状态的特殊二叉查找树
-
B树:一种特殊的二叉树,数据库用它于存储数据
-
堆:
-
伸展树:
搜索引擎的原理
-
反向索引:创建一个散列表,将键为单词,值为包含指定单词的页面,一个散列表,将单词映射到包含它的页面。
-
傅里叶变换:强化你关心的部分,用于处理信号。
-
并行算法:多个内核中并行的处理。
并行性管理开销
负载均衡
分布式算法:一种特殊的并行算法,MapReduce。用于短时间内完成,海量工作。
- 映射(map)函数:接受一个数组,对每个元素执行同样的处理。
- 归并(reduce)函数:将很多项归并为一项。一个数组转换为一个元素。
- 布隆过滤器:一种概率型数据结构,提供的答案可能对,也可能不对。很可能正确。占用存储空间很少。
HyperLogLog:一种类似布隆过滤器算法,答案比较接近准确,占用内存少。
SHA算法(安全散列算法):给定一个字符串,返回其散列值。局部不敏感。
- 可以用于判断俩个文件是否相同。
- 检查密码,存储哈希值。
- 局部不敏感。simhash。
- Diffie-Hellman密钥交换。
公钥:用于加密消息
私钥:用于解密消息
RSA算法
线性规划:最优化,在给定约束条件下最大限度地改善指定的指标。
Simplex算法。
评论