数组与链表的区别
1.需要随机读取的时候,数组的效率很高。
2.跨越读取的时候, 链表更有优势。链表擅长插入和删除。
递归只是让解决方案更清晰,并没有性能上的优势
递归函数都有两部分:基线条件(base case)和递归条件(recursive case)
调用栈(call stack)
一叠便条:插入的待办事项放在清单的最前面;读取待办事项时,你只读取最上面的那个,并将其删除。因此这个待办事项清单只有两种操作:压入(插入)和弹出(删除并读取)。
D&C (divide and conquer)分而治之
每次递归调用都必须缩小问题的规模。
1.找出简单的基线条件
2. 确定如何缩小问题的规模,使其符合基线条件。
递归记录了状态
散列表
使用散列函数和数组创建了一种被称为散列表(hash table)的数据结构.
数组和链表都被直接映射到内存中,但散列表更复杂,它使用散列函数来确定元素的存储位置。也被称为散列映射、字典和关联数组。
仿真映射关系;
防止重复;
缓存/记住数据,以免服务器再通过处理来生成它们。
在平均情况下,散列表的查找(获取给定索引处的值)速度与数组一样快,而插入和删除速度与链表一样快,因此它兼具两者的优点!最糟情况下都很慢。为此,需要避免冲突,需要有:
较低的填装因子;
良好的散列函数。
散列表的优点
你可以结合散列函数和数组来创建散列表。
冲突很糟糕,你应使用可以最大限度减少冲突的散列函数。
散列表的查找、插入和删除速度都非常快。
散列表适合用于仿真映射关系。
一旦填装因子超过0.7,就该调整散列表的长度。
散列表可用于缓存数据(例如,在Web服务器上)。
散列表非常适合用于防止重复。
队列
队列和现实生活中的队列完全相同。假设你与朋友一起在公交车站排队,如果你排在他前面,你讲先上车。队列的工作原理榆次相同。队列类似于栈,你不能随机地访问队列中的元素。队列只支持两种操作:入队和出列。
队列是一种先进先出的数据结构。
狄克斯特拉算法背后的关键理念:
找出图中最便宜的节点,并确保没有到该节点更便宜的路径
动态规划
需要在给定约束条件下优化某种指标时,很有用。
问题可分解为离散子问题,可使用动态规划来解决。
每种动态规划解决方案都设计网格。
单元格中的值通常都是你要优化的值。
每个单元格都是一个子问题,因此你需要考虑如何将问题分解为子问题。
没有放之四海而皆准的计算动态规划解决方案的公式。
K最近邻算法
分类
分类就是编组
回归
回归就是预测结果(如一个数字)
特征抽取意味着将物品(如水果或用户)转换为一系列可比较的数字。 能否挑选合适的特征事关KNN算法的成败。
B树-特殊的二叉树
数据库常用它来存储数据。类似的还有B树,红黑树,堆,伸展树。
MapReduce
并行算法速度的提升并非线性的。原因是:并行性管理开销: 假设你要对一个包含1000个元素的数组进行排序,如何在两个内核之间分配这项任务呢?如果让每个内核对其中500个元素进行排序,再将两个排好序的数组合并成一个有序数组,那么合并也是需要时间的。
**负载均衡 。**假设你需要完成10个任务,因此你给每个内核都分配5个任务。但分配给内核A的任务都很容易,10秒钟就完成了,而分配给内核B的任务都很难,1分钟才完成。这意味着有那么50秒,内核B在忙死忙活,而内核A却闲得很!你如何均匀地分配工作,让两个内核都一样忙呢?
分布式计算利用两个简单的理念:映射(map)函数和归并(reduce)函数。
映射函数:接受一个数组,并对其中的每个元素执行同样的处理。
归并函数:其理念是将很多项归并为一项。如映射是将一个数组转换为另一个数组,归并是将一个数组转换为一个元素。
布隆过滤器
布隆过滤器提供了解决之道。布隆过滤器是一种概率型数据结构 ,它提供的答案有可能不对,但很可能是正确的。为判断网页以前是否已搜集,可不使用散列表,而使用布隆过滤器。使用散列表时,答案绝对可靠,而使用布隆过滤器时,答案却是很可能是正确的。
SHA(secure hash algorithm)
你可使用SHA来判断两个文件是否相同,这在比较超大型文件时很有用。假设你有一个4 GB的文件,并要检查朋友是否也有这个大型文件。为此,你不用通过电子邮件将这个大型文件发送给朋友,而可计算它们的SHA散列值,再对结果进行比较。
可以用来比较文件和检查密码。
[美] Aditya Bhargava. 算法图解 (Kindle 位置 2239-2241). 人民邮电出版社. Kindle 版本.