这是一本很入门的算法书,介绍的东西还算简单明了,大体补充了一些自己没理解的东西.
粗略地看了一下,感觉还是"纸上得来终觉浅,绝知此事要躬行!"
O(n)线性时间,简单查找,n表示操作数
O(log n)对数时间,二分查找
O(n * log n)快速排序
O(n^2)选择排序
O(n!)旅行商问题
数组的元素都在一起
链表的元素是分开的,其中每个元素都存储了下一个元素的地址
常见数组和链表操作的运行时间
O(n)线性时间 ; O(1)常量时间
链表擅长插入和删除,而数组擅长随机访问
每个递归函数都有两部分:基线条件(base case)和递归条件(recursive case)。
递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自己,从而避免形成无限循环。
压入和弹出
调用栈可能很长,这将占用大量的内存。
(divide and conquer,D&C)——一种著名的递归式问题解决方法
D&C算法——快速排序
D&C的工作原理:
(1) 找出简单的基线条件;
(2) 确定如何缩小问题的规模,使其符合基线条件。
首先,从数组中选择一个元素,这个元素被称为基准值(pivot)
接下来,找出比基准值小的元素以及比基准值大的元素。这被称为分区(partitioning).
实现快速排序时,请随机地选择用作基准值的元素。快速排序的平均运行时间为O(n log n)。
比较简单查找和二分查找时,常量几乎无关紧要,因为列表很长时,O(log n)的速度比O(n)
快得多。
散列表操作所需的时间为O(1)
散列表的查找、插入和删除速度都非常快
散列函数: 将输入映射到数字
例子:
冲突(collision)
如果两个键映射到了同一个位置,就在这个位置存储一个链表。
但是这样会影响散列表的速度.需要一个好的散列函数将键均匀地映射到散列表的不同位置.
一旦填装因子大于0.7,就调整散列表的长度(resizing), 通常将数组增长一倍
breadth-first search, BFS , 让你能够找出两样东西之间的最短距离!
解决最短路径问题(shortest-path problem)的算法被称为广度优先搜索
队列只支持两种操作:入队和出队。
队列是一种先进先出(First In First Out,FIFO)的数据结构,
而栈是一种后进先出(Last In First Out,LIFO)的数据结构。
有向图(directed graph)
无向图(undirected graph)
运行时间:
每个顶点为O(1),每条边为O(1)
总运行时间O(V + E), V为顶点(vertice),E为边数
注意:
你需要按加入顺序检查搜索列表中的人,否则找到的就不是最短路径,因此搜索列表必
须是队列。
对于检查过的人,务必不要再去检查,否则可能导致无限循环。
每条边都有关联数字的图,这些数字称为权重(weight)。
带权重的图称为加权图(weighted graph),不带权重的图称为非加权图(unweighted graph)。
狄克斯特拉算法用于在加权图中查找最短路径。
仅当权重为正时狄克斯特拉算法才管用。
贪婪算法的优点—简单易行. 每步都选择局部最优解,最终得到的就是全局最优解
但在有些情况下,完美是优秀的敌人, 贪婪算法不能获得最优解
贪婪算法寻找局部最优解,企图以这种方式获得全局最优解。
近似算法(approximation algorithm)
列出每个可能的广播台集合,这被称为幂集(power set)
(1) 选出这样一个广播台,即它覆盖了最多的未覆盖州。即便这个广播台覆盖了一些已覆盖
的州,也没有关系。
(2) 重复第一步,直到覆盖了所有的州。
贪婪算法易于实现、运行速度快,是不错的近似算法
NP完全问题
旅行商问题: 是一个 阶乘函数(factorial function),n!.
近似求解: 随便选择出发城市,然后每次选择下一个没去的最近的城市.
对于NP完全问题,还没有找到快速解决方案。
面临NP完全问题时,最佳的做法是使用近似算法。
动态规划可帮助你在给定约束条件下找到最优解。
在问题可分解为彼此独立且离散的子问题时,就可使用动态规划来解决。
每种动态规划解决方案都涉及网格。
单元格中的值通常就是你要优化的值。
每个单元格都是一个子问题,因此你应考虑如何将问题分成子问题,这有助于你找出网格的坐标轴
费曼算法(Feynman algorithm)
(1) 将问题写下来。
(2) 好好思考。
(3) 将答案写下来。
最长公共子序列的解决方案:
K最近邻(k-nearest neighbours,KNN)算法
KNN用于分类和回归,需要考虑最近的邻居。
特征抽取意味着将物品(如水果或用户)转换为一系列可比较的数字。
能否挑选合适的特征事关KNN算法的成败。
机器学习
OCR指的是光学字符识别(optical character recognition),这意味着你可拍摄印刷页面的照片,
计算机将自动识别出其中的文字。
如何自动识别出这个数字是什么呢?可使用KNN。
(1) 浏览大量的数字图像,将这些数字的特征提取出来。 称为训练(training)
(2) 遇到新图像时,你提取该图像的特征,再找出它最近的邻居都是谁!
一般而言,OCR算法提取线段、点和曲线等特征。
垃圾邮件过滤器
垃圾邮件过滤器使用一种简单算法——朴素贝叶斯分类器(Naive Bayes classifier),你首先
需要使用一些数据对这个分类器进行训练。
假设你收到一封主题为“collect your million dollars now!”的邮件,这是垃圾邮件吗?你可研
究这个句子中的每个单词,看看它在垃圾邮件中出现的概率是多少。例如,使用这个非常简单的
模型时,发现只有单词million在垃圾邮件中出现过。
预测股票市场
根据以往的数据来预测未来方面, 由于涉及的变数太多,这几乎是不可能完成的任务
二叉查找树(binary search tree)
对于其中的每个节点,左子节点的值都比它小,而右子节点的值都比它大。
在二叉查找树中查找节点时,平均运行时间为O(log n),但在最糟的情况下所需时间为O(n);而在有序数组中查找时,即便是在最糟情况下所需的时间也只有O(log n).
这棵树是向右倾斜的,因此性能不佳.
请研究如下数据结构:B树,红黑树,堆,伸展树。
反向检索
一个散列表,将单词映射到包含它的页面。这种数据结构被称为反向索引(inverted index),常用于创建搜索引擎
傅里叶变换
傅里叶变换非常适合用于处理信号,可使用它来压缩音乐。为此,首先需要将音频文件分解为音符。傅里叶变换能够准确地指出各个音符对整个歌曲的贡献,让你能够将不重要的音符删除。这就是MP3格式的工作原理!
并行算法
MapReduce 分布式算法 MapReduce是一种流行的分布式算法,你可通过流行的开源工具Apache Hadoop来使用它。
MapReduce基于两个简单的理念:映射(map)函数和归并(reduce)函数。