1.解决最短路径问题(shortest-path problem)的算法被称为广度优先搜索(breadth first search)。
2.图由节点(node)和边(edge)组成,一个节点可能与众多节点直接相连,这些节点被称为邻居,图用于模拟不同的东西是如何相连的。
3.广度优先搜索(BFS)是一种用于图的查找算法,可帮助回答两类问题。第一类问题:从节点A出发,有前往节点B的路径吗?第二类问题:从节点A出发,前往节点B的哪条路径最短?
4.队列类似于栈,不能随机地访问队列中的元素,队列只支持两种操作:入队和出队,是一种FIFO数据结构,而栈是LIFO数据结构,队列可用于BFS。
5.散列表可用于实现图,并且散列表是无序的,添加键值对的顺序无关紧要。将散列表中的数据加入队列数据结构,实现BFS。
6.在Python中,可使用函数deque来创建一个双端队列。
from collections import deque
图中可能有一个节点同时是两个人的邻居,在加入队列便于BFS时可能会出现循环的情况,因此在检查一个人前应该先检查这个人是不是已经检查过了(用一个数组实现)。队列的数据表达形式和列表很像?
7.先用散列表(dict)实现图,然后用队列实现BFS。BFS的运行时间为O (V + E ),其中V 为(存入队列的)顶点(vertice)数,E为(图的)边数。
8.如果任务A依赖于任务B,在列表中任务A就必须在任务B后面,这被称为拓扑排序。树是一种特殊的图,没有往后指的边。
9.面临类似于寻找最短路径的问题时,可尝试使用图来建立模型,再使用广度优先搜索(BFS)来解决问题。
1.狄克斯特拉算法(Dijkstra’s algorithm),解决最快路径的问题,包括四个步骤:(1) 找出最便宜的节点,即可在最短时间内前往的节点,并确保没有到该节点的更便宜的路径。(2) 对于该节点的邻居,检查是否有前往它们的更短路径,如果有,就更新其开销。 (3) 重复这个过程,直到对图中的每个节点都这样做了。 (4) 计算最终路径。最短路径指的并不一定是物理距离,也可能是让某种度量指标最小。
2.带权重的图称为加权图(weighted graph),不带权重的图称为非加权图(unweighted graph)。要计算非加权图中的最短路径,可使用广度优先搜索(BFS)。要计算加权图中的最短路径,可使用狄克斯特拉算法。在无向图中,两个节点彼此指向对方,其实就是环,每条边都是一个环,狄克斯特拉算法只适用于有向无环图 (directed acyclic graph,DAG),并且如果有负权边,也不能使用狄克斯特拉算法,在包含负权边的图中,要找出最短路径,可使用另一种算法:贝尔曼-福德算法(Bellman-Ford algorithm)。
1.教室调度问题:使用贪心算法解决,每步都采取局部最优解,最终得到的就是全局最优解,在这个问题中是每次都选择结束最早的课。
2.背包问题:有时候只需找到一个能够大致解决问题的算法,此时贪婪算法正好可派上用场,因为它们实现起来很容易,得到的结果又与正确结果相当接近。
3.集合覆盖问题:运行时间本来是O(2n),但用贪心算法之后时间变为O(n2)?python中创建集合用set函数,类似于列表,但集合中的值只能出现一次,使用集合来表示一切可以简化工作。并集符号:|,交集符号:&,差集符号:-。
4.出现错误:AttributeError: ‘NoneType’ object has no attribute ‘items’。很有可能粗心大意在生成变量的函数最后忘记返回这个变量了。
5.快速排序不是贪心算法(是递归的),广度优先搜索和狄克斯特拉算法是贪心算法。
6.旅行商问题是np完全问题(O(n!))(教室调度问题?、背包问题、集合覆盖问题都是np完全问题,背包可用动态规划求最优解,教室调度、集合覆盖可用贪心算法求最接近最优解的近似解),可近似求解,如贪心算法解决。狄克斯特拉算法解决的最短路径是从a点到b点求最短路径,但如果要找出经由指定几个点的最短路径(出发点和到达点没有明确,可以自由组合的)成了旅行商问题(np完全问题)。
7.没办法判断问题是不是NP完全问题,但还是有一些蛛丝马迹可循的(见书P255):
(1)元素较少时算法的运行速度非常快,但随着元素数量的增加,速度会变得非常慢。
(2)涉及“所有组合”的问题通常是NP完全问题。
(3)不能将问题分成小问题,必须考虑各种可能的情况,这可能是NP完全问题。
(4)如果问题涉及序列(如旅行商问题中的城市序列)且难以解决,它可能就是NP完全问题。
(5)如果问题涉及集合(如广播台集合)且难以解决,它可能就是NP完全问题。
(6)如果问题可转换为集合覆盖问题或旅行商问题,那它肯定是NP完全问题。
8.贪心算法寻找局部最优解,并企图以这种方式获得全局最优解,实际一般求得近似解,运行时间是O(n^2)。对于NP完全问题(运行时间是O(n!),还没有找到快速解决方案,最佳的做法是使用近似算法,贪心算法易于实现、运行速度快,是不错的近似算法。
1,动态规划将问题分成小问题,并先着手解决这些小问题,然后再解决大问题。
2.使用动态规划解决背包问题时,要么考虑拿走整件商品,要么考虑不拿,而没法判断该不该拿走商品的一部分。但贪心算法可以解决,首先,尽可能多地拿价值最高的商品,如果拿光了,再尽可能多地拿价值次高的商品,依次类推。
3.动态规划功能强大,它能够解决子问题并使用这些答案来解决大问题,但仅当每个子问题都是离散的,即不依赖于其他子问题时,动态规划才管用。并且动态规划可在给定约束条件下找到最优解。
4.但最优解(价值最大)也有可能导致背包没有装满。
5.例题9.2:
1磅 | 2磅 | 3磅 | 4磅 | 5磅 | 6磅 | |
---|---|---|---|---|---|---|
水(3磅,价值10)w | 0 | 0 | 10 w | 10 w | 10 w | 10 w |
书(1磅,价值3)b | 3 b | 3 b | 10 w | 13 wb | 13 wb | 13 wb |
食物(2磅,价值9)f | 3 b | 9 f | 12 fb | 13 wb | 19 wf | 22 wfb |
夹克(2磅,价值5)j | 3 b | 9 f | 12 fb | 14 fj | 19 wf | 22 wfb |
相机(1磅,价值6)c | 6 c | 9 f/cb | 15 fc | 18 fbc | 20 fjc | 25 wfc |
携带水、食物、相机价值最大
6.最长公共子串、最长公共序列(动态规划解决)需要再学习。
7.动态规划的公式并没有可用于所有情况的。
8.例题9.3:计算blue和clues最长公共子串
c | l | u | e | s | |
---|---|---|---|---|---|
b | 0 | 0 | 0 | 0 | 0 |
l | 0 | 1 | 0 | 0 | 0 |
u | 0 | 0 | 2 | 0 | 0 |
e | 0 | 0 | 0 | 3 | 0 |
1.KNN做两项基本工作——分类和回归:分类就是对当前样本编组;回归就是对于最近的几个邻居的结果做平均,从而预测当前样本的结果(如一个数字)。相似度比较时用到欧式距离或余弦相似度公式(夹角余弦),余弦相似度不计算两个矢量的距离,而比较它们的角度。
2.机器学习例子:创建推荐系统,OCR(光学字符识别)(一般而言,OCR算法提取线段、点和曲线等特征),创建垃圾邮件过滤器,但用机器学习预测股票市场不可能实现。
3.能否挑选合适的特征事关KNN算法的成败。
1.树:数据结构二叉查找(排序)树(binary search tree),对于其中的每个节点,左子节点的值都比它小,而右子节点的值都比 它大,在二叉查找树中查找节点时,平均运行时间为O (log n ),但在最糟的情况下所需时间为O (n);而在有序数组中二分(折半)查找时,即便是在最糟情况下所需的时间也只有O(log n);二叉查找树的插入和删除操作的速度比数组的O(n)要快得多(O(log n));二叉查找树不能随机访问(和数组一样可以指定访问第几个元素),在二叉查找树处于平衡状态时,平均访问时间也为O (log n )。
B树(平衡二叉树,又称AVL树),B+树的区别参考链接:https://www.cnblogs.com/lianzhilei/p/11250589.html(待学习)
AVL(高度平衡的二叉搜索树,又称B树)与红黑树(R-B树,红黑树也是二叉查找树,统计性能要好于平衡二叉树)的区别和联系,在C++ STL中,很多部分(目前包括set,multiset, map, multimap)都应用了红黑树的变体,参考连接:https://www.cnblogs.com/rednodel/p/9259134.html(待学习)
2.反向索引:用一个散列表,将单词映射到包含它的页面。这种数据结构被称为反向索引(inverted index),常用于创建搜索引擎。
3.傅立叶变换:一个网站Better Explained致力于以通俗易懂的语言阐释数学:https://betterexplained.com/。
傅立叶用于处理数字信号,可压缩音乐、JPG也是一种压缩格式、用于地震预测和DNA分析等。
4.并行算法:对于算法速度的提升并非线性的。
5.MapReduce:一种流行的分布式算法,可通过开源工具Apache Hadoop来使用它。分布式算法非常适合用于在短时间内完成海量工作,其中的MapReduce基于两个简单的理念:映射(map)函数和归并(reduce)函数。映射是将一个数组转换为另一个数组,归并函数理念是将很多项归并为一项(将一个数组转换为一个元素)。MapReduce使用这两个简单概念在多台计算机上执行数据查询(数据集很大)。
6.布隆过滤器和HyperLogLog:
布隆过滤器是一种概率型数据结构,它提供的答案有可能不对,但很可能是正确的,如为google搜集未搜索过的网页时:可能出现错报的情况,即Google可能指出“这个网站已搜集”,但实际上并没有搜集;不可能出现漏报的情况,即如果布隆过滤器说“这个网站未搜集”,就肯定未搜集。
HyperLogLog近似地计算集合中不同的元素数,与布隆过滤器一样,它不能给出准确的答案,但也八九不离十,而占用的内存空间却少得多。面临海量数据且只要求答案八九不离十时,可考虑使用概率型算法。
7.SHA算法:secure hash algorithm(安全散列算法),给定一个字符串,SHA返回其散列值(一个较短的字符串)。用于创建散列表的散列函数根据字符串生成数组索引,而SHA根据字符串生成另一个字符串。
用处:(1)通过比较两个或以上文件的SHA散列值,判断是否是同一个文件;(2)检查密码,如:Gmail只存储密码的SHA散列值,不存储密码,避免黑客攻击。SHA实际上是一系列算法:SHA-0、SHA-1、SHA-2和SHA-3。
SHA算法是局部不敏感的,即:假设对一个字符串计算了其散列值,如果修改其中一个字符,在计算其散列值,结果完全不同。
8.局部敏感的散列算法:可使用Simhash,如果对字符串做细微的修改,Simhash生成的散列值也只存在细微的差别。这样可以通过比较散列值来判断两个字符串的相似程度。
用处:(1)Google使用Simhash来判断网页是否已搜集。(2)老师可以使用Simhash来判断学生的论文是否是从网上抄的。(3)Scribd允许用户上传文档或图书,以便与人分享,但不希望用户上传有版权的内容,这个网站可使用Simhash来检查上传的内容是否与小说《哈利·波特》类似,如果类似,就自动拒绝。
需要检查两项内容的相似程度时,Simhash很有用。
9.Diffie-Hellman密钥交换:RSA算法也可以了解。
10.线性规划:用于在给定约束条件下最大限度地改善指定的指标,所有的图算法都可使用线性规划来实现,线性规划是一个宽泛得多的框架,图问题只是其中的一个子集。可了解Simplex算法。