《算法图解》读书笔记

这是一本很入门的算法书,介绍的东西还算简单明了,大体补充了一些自己没理解的东西.
粗略地看了一下,感觉还是"纸上得来终觉浅,绝知此事要躬行!"

<<算法图解>>读书笔记

1.算法介绍

大O表示法

O(n)线性时间,简单查找,n表示操作数

O(log n)对数时间,二分查找

O(n * log n)快速排序

O(n^2)选择排序

O(n!)旅行商问题

《算法图解》读书笔记_第1张图片

  • 算法的速度指的并非时间,而是操作数的增速。
  • 谈论算法的速度时,我们说的是随着输入的增加,其运行时间将以什么样的速度增加。
  • 算法的运行时间用大O表示法表示。
  • O(log n)比O(n)快,当需要搜索的元素越多时,前者比后者快得越多

2.选择排序

数组

数组的元素都在一起

  • 优点:
    • 读取数据很快
  • 缺点:
    • 事件超出数组长度,需要转移
    • 如果预留额外空间,会造成内存的浪费

链表

链表的元素是分开的,其中每个元素都存储了下一个元素的地址

  • 优点:
    • 插入和删除速度很快
  • 缺点:
    • 读取链表最后一个元素,无法直接读取

常见数组和链表操作的运行时间

《算法图解》读书笔记_第2张图片

O(n)线性时间 ; O(1)常量时间

链表擅长插入和删除,而数组擅长随机访问

3.递归

每个递归函数都有两部分:基线条件(base case)和递归条件(recursive case)。
递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自己,从而避免形成无限循环。

压入和弹出

调用栈可能很长,这将占用大量的内存。

4. 快速排序

(divide and conquer,D&C)——一种著名的递归式问题解决方法

D&C算法——快速排序

D&C的工作原理:
(1) 找出简单的基线条件;
(2) 确定如何缩小问题的规模,使其符合基线条件。

首先,从数组中选择一个元素,这个元素被称为基准值(pivot)
接下来,找出比基准值小的元素以及比基准值大的元素。这被称为分区(partitioning).

  • 实现快速排序时,请随机地选择用作基准值的元素。快速排序的平均运行时间为O(n log n)。

  • 比较简单查找和二分查找时,常量几乎无关紧要,因为列表很长时,O(log n)的速度比O(n)
    快得多。

    • 大O表示法中O(n)中的n实际上是c * n,c是算法所需的固定时间量,称为常量.
      例如,简单查找 10ms * 40亿=463天; 二分查找 1s * log 40亿 = 32s

5.散列表(hash table)

散列表操作所需的时间为O(1)

散列表的查找、插入和删除速度都非常快

散列函数: 将输入映射到数字

例子:

  1. 将网址映射到IP地址—即DNS解析(DNS resolution)
  2. 搜索引擎,网站将问题的数据缓存,而不必再重新计算
  • 散列表适合用于:
    • 模拟映射关系;
    • 防止重复;
    • 缓存/记住数据,以免服务器再通过处理来生成它们

冲突(collision)

如果两个键映射到了同一个位置,就在这个位置存储一个链表。
但是这样会影响散列表的速度.需要一个好的散列函数将键均匀地映射到散列表的不同位置.

  • 避免冲突,需要有:
    • 较低的填装因子;(填装因子=散列表包含的元素数/位置总数)
    • 良好的散列函数。

一旦填装因子大于0.7,就调整散列表的长度(resizing), 通常将数组增长一倍

6.广度优先搜索

breadth-first search, BFS , 让你能够找出两样东西之间的最短距离!

解决最短路径问题(shortest-path problem)的算法被称为广度优先搜索

队列(queue)

队列只支持两种操作:入队和出队。

队列是一种先进先出(First In First Out,FIFO)的数据结构,
而栈是一种后进先出(Last In First Out,LIFO)的数据结构。

《算法图解》读书笔记_第3张图片

有向图(directed graph)
无向图(undirected graph)

《算法图解》读书笔记_第4张图片

算法原理

  1. 创建一个队列,用于存储需要检查的人
  2. 从队列中弹出一个人
  3. 检查是否符合
  4. 是:大功告成
    否:将这个人所有的邻居加入队列
  5. 回到第2步
  6. 如果队列为空,说明没有任何人符合

运行时间:
每个顶点为O(1),每条边为O(1)
总运行时间O(V + E), V为顶点(vertice),E为边数

注意:
你需要按加入顺序检查搜索列表中的人,否则找到的就不是最短路径,因此搜索列表必
须是队列。
对于检查过的人,务必不要再去检查,否则可能导致无限循环。

7.狄克斯特拉算法

  • 狄克斯特拉算法包含4个步骤。
    (1) 找出最便宜的节点,即可在最短时间内前往的节点。
    (2) 对于该节点的邻居,检查是否有前往它们的更短路径,如果有,就更新其开销。
    (3) 重复这个过程,直到对图中的每个节点都这样做了。
    (4) 计算最终路径。

每条边都有关联数字的图,这些数字称为权重(weight)。

带权重的图称为加权图(weighted graph),不带权重的图称为非加权图(unweighted graph)。

《算法图解》读书笔记_第5张图片

狄克斯特拉算法用于在加权图中查找最短路径。
仅当权重为正时狄克斯特拉算法才管用。

8.贪婪算法

贪婪算法的优点—简单易行. 每步都选择局部最优解,最终得到的就是全局最优解

但在有些情况下,完美是优秀的敌人, 贪婪算法不能获得最优解

贪婪算法寻找局部最优解,企图以这种方式获得全局最优解。

近似算法(approximation algorithm)

列出每个可能的广播台集合,这被称为幂集(power set)

(1) 选出这样一个广播台,即它覆盖了最多的未覆盖州。即便这个广播台覆盖了一些已覆盖
的州,也没有关系。
(2) 重复第一步,直到覆盖了所有的州。

贪婪算法易于实现、运行速度快,是不错的近似算法

NP完全问题

旅行商问题: 是一个 阶乘函数(factorial function),n!.

近似求解: 随便选择出发城市,然后每次选择下一个没去的最近的城市.

对于NP完全问题,还没有找到快速解决方案。
面临NP完全问题时,最佳的做法是使用近似算法。

9.动态规划

动态规划可帮助你在给定约束条件下找到最优解。

在问题可分解为彼此独立且离散的子问题时,就可使用动态规划来解决。

每种动态规划解决方案都涉及网格。

单元格中的值通常就是你要优化的值。
每个单元格都是一个子问题,因此你应考虑如何将问题分成子问题,这有助于你找出网格的坐标轴

费曼算法(Feynman algorithm)

(1) 将问题写下来。
(2) 好好思考。
(3) 将答案写下来。

最长公共子序列的解决方案:

《算法图解》读书笔记_第6张图片

  • 动态规划都有哪些实际应用呢?
    • 生物学家根据最长公共序列来确定DNA链的相似性,进而判断度两种动物或疾病有多相
      似。最长公共序列还被用来寻找多发性硬化症治疗方案。
    • 你使用过诸如git diff等命令吗?它们指出两个文件的差异,也是使用动态规划实现的。
    • 前面讨论了字符串的相似程度。编辑距离(levenshtein distance)指出了两个字符串的相
      似程度,也是使用动态规划计算得到的。编辑距离算法的用途很多,从拼写检查到判断
      用户上传的资料是否是盗版,都在其中。
    • 你使用过诸如Microsoft Word等具有断字功能的应用程序吗?它们如何确定在什么地方断
      字以确保行长一致呢?使用动态规划!

10.K最近邻算法

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在垃圾邮件中出现过。

预测股票市场

根据以往的数据来预测未来方面, 由于涉及的变数太多,这几乎是不可能完成的任务

11.树

二叉查找树(binary search tree)

对于其中的每个节点,左子节点的值都比它小,而右子节点的值都比它大。

在二叉查找树中查找节点时,平均运行时间为O(log n),但在最糟的情况下所需时间为O(n);而在有序数组中查找时,即便是在最糟情况下所需的时间也只有O(log n).

《算法图解》读书笔记_第7张图片

这棵树是向右倾斜的,因此性能不佳.

请研究如下数据结构:B树,红黑树,堆,伸展树。

反向检索

一个散列表,将单词映射到包含它的页面。这种数据结构被称为反向索引(inverted index),常用于创建搜索引擎

傅里叶变换

傅里叶变换非常适合用于处理信号,可使用它来压缩音乐。为此,首先需要将音频文件分解为音符。傅里叶变换能够准确地指出各个音符对整个歌曲的贡献,让你能够将不重要的音符删除。这就是MP3格式的工作原理!

并行算法

MapReduce 分布式算法 MapReduce是一种流行的分布式算法,你可通过流行的开源工具Apache Hadoop来使用它。

MapReduce基于两个简单的理念:映射(map)函数和归并(reduce)函数。

你可能感兴趣的:(数据看点,算法图解,算法)