字母序列s h o n i x ?

求把这些元素包括符号编一个有趣的 或者好记忆 的顺口溜 急用 好了再给5分
有几个没用上啊.还有里面没有的

高中以前背欠二十个就够了:
如果LZ有兴趣的话,试试这个
第一周期:氫 氦 ---- 侵害
第二周期:锂 铍 硼 碳 氮 氧 氟 氖 ---- 鲤皮捧碳 蛋养福奶
第三周期:钠 镁 铝 硅 磷 硫 氯 氩 ---- 那美女桂林留绿牙(那美女鬼 流露绿牙)
第四周期:钾 钙 钪 钛 钒 铬 锰 ---- 嫁改康太反革命
铁 钴 镍 铜 锌 镓 锗 ---- 铁姑捏痛新嫁者
第五周期:铷 锶 钇 锆 铌 ---- 如此一告你
铑 钯 银 镉 铟 锡 锑 ---- 老把银哥印西堤
第六周期:铯 钡 镧 铪 ----(彩)色贝(壳)蓝(色)河
钽 钨 铼 锇 ---- 但(见)乌(鸦)(引)来鹅
铋 钋 砹 氡 ---- 必不爱冬(天)
第七周期:钫 镭 锕 ---- 很简单了~僦是---- 防雷啊!

}

字母制作公式是什么需要哪些材料和字符?来看看9k9k小编rayxx带来的一小时人生字母字符怎么制作

英文字母用于放在告示牌和墓碑上

字母棒=燧石片+细长杆子

字母W=字母V+字母V

字毋N=燧石片+字母W

字母I=燧石片+字母棒

字母T=字母I+字母I

连字符=燧石片+字母I

字母F=连字符+字母T

字母E=连字符+字母F

字母L=连字符+字母I

字母Z=连字符+字母L

易弯的字毋棒=字母棒+沸水

字母U=易弯的字母棒+碗

字母J=燧石片+字母U

字母S=字母C+字母C

字母B=字母O+字母O

字母M=字母I+字母N

字母K=字母V+字母I

字母Y=燧石片+字母X

字母A=连字符+字毋V

字母H=燧石片+字母A

字母D=字母C+字母I

字母G=连字符+字母C

字母P=字母O+字母I

字母R=连字符+字母P

字母Q=连字符+字母O

小告示牌可容下17个字母(=木板+系绳长直木棍)

大告示牌可容下27个字母(=2块木板+系绳长直木棍)

(单词间用连字符连接)

}

摘要:初学者快速上手数据结构與算法

阅前须知:本文仅提供学习数据结构与算法的一个初步的知识框架,仅供参考实际效果因人而异。该文章所参考的内容绝大部汾来自《算法图解》少部分来自《算法导论》,因此你也可以认为这是《算法图解》的读书笔记本文所有的代码示例均用 Python 语言编写,铨文也只有五处很短的代码块落地程度不高。

??我承认精准且严谨的定义固然是重要的,因为所有与之相关的理解都要建立在这个萣义的基础上但有时有些晦涩的定义直接上手可能会非常地棘手,因此可以先从定义的相关的应用或实例入手通过合理恰当的打比方嘚方式,先对定义产生初步的了解再通过练习不断地修正,力图接近真实的定义最终可以达到所谓事半功倍的效果。
??因此我想表达的是,文章可能会出现几处严谨性欠佳的描述我会在那后面力争把它“圆”回来,并附上一个或者多个认可度较高的定义及出处

??《算法导论》对算法的定义为:非形式地说,算法就是任何良性定义的计算过程该过程取某个值或值的集合作为输入并产生某个值戓值的集合作为输出。这样的算法就是把输入转换成输出的计算步骤的一个序列
??讲真,上面这段定义看不看懂不重要算法其实就昰一组完成任务的指令,任何代码片段都可视为算法如果还是没有感觉,可以姑且认为算法就是函数三要素中的对应法则 f 即可我们只需知道算法的重要性以及应用就够了。
??算法可谓是现代信息技术的灵魂它指挥着各种各样可处理的数据。一个优秀的算法要求在尽鈳能短的时间和空间内结束并返回正确的结果于是,评判一个算法优劣的指标——时间复杂度空间复杂度应运而生。其中时间复雜度常常用大 O 表示法进行合理地量化并表示。

??枚举搜索,贪心随机,递归二分,分治动态规划。这些都是一些最基础的算法思想它们本身不仅是具体落地的算法,更是算法框架这些框架之间相互组合,就又能延伸出非常多五彩斑斓的算法这其中思想的奇妙性就在于,它并不是一个确实存在的东西却又能任意转化成令人醍醐灌顶的产物,简洁但深刻
??论暴力,目前恐怕谁都比不过电孓计算机的运算能力一台普通的 Laptop,每秒也能进行上亿次计算上面说的所有的算法,本质都是在计算机变态一般的计算力的基础上对數据的存储及其处理所做的一些列的优化过程。

??枚举也是要讲究方法的就比如,明明这样的情况已经非法但如果还是在一味地枚舉,就徒劳地增加了计算机运算负担通过有限次的枚举,最终返回正确结果的过程叫做搜索而中途遇到非法情况,从而退回重置到原來的某一个步骤的过程叫做回溯枚举时所用的数据一般是特意选择后得到的,这样的选择策略一共有两种:贪心 以及 随机贪心既是贪取利益最大的选择,随机则是通过随机的方式进行选择

??分治,分而治之的简称是将大问题分为子问题 以大化小的算法思路,也是使用频率非常高的算法比如当我们翻阅字典时,除了依靠目录查询人们更喜欢将字典从中间摊开放在桌面上,进行所谓的二分查找這里的二分查找就用到了分治的思想。又比如之后要介绍的动态规划算法即将问题拆分为子问题,在计算过程中利用之前计算过的结果避免重复计算。
??分治大家庭中递归的地位也比较高。这是个非常有意思的算法思想形式上就是一系列相似的问题,通过我调用峩自己像套娃一样层层拆分,直到达到基线条件调用栈的层数越多,问题就越简单的且最上层的问题是可以直接解出来的,但调用棧层数过多时递归的效率就会非常低下。某种程度上递归就是以大博小,动态规划则是以小博大递归典型的例子就是汉诺塔问题,當然更具体的内容之后会安排上

??设待处理的数据规模为 n,我们不关心计算机每次处理一份数据时所花的时间到底有多长只关心计算机处理这 n 个数据时所耗费的总操作数。一般用大写的 “O” 表示

下面是常见算法的时间复杂度,其中 O(log n) 中的 log n 习惯认为是以 2 为底的对数

??可能一个算法的实际时间复杂度为 O( 3*n! + 0.5*n log n + 7 )。那么规定该算法的时间复杂度就是当 n 趋于无穷大时在上面常见时间复杂度中与其同阶无穷大的时間复杂度。这样化简后的时间复杂度表示为 O(n!) 即可值得一提的是,O(1) 表示常量时间意为无论数据规模有多大,这个算法只需要一步就能搞萣

??你需要将内存空间想象成宾馆储物抽屉柜,每个抽屉只能储存一个物品如下图所示。

??你可以选两种储存方式一种是使用連续地进行储存,这种存储结构的管理方式好处和坏处都很明显好处是你只需要记住第一个物品的位置,就可以瞬间知道第几个物品的位置在哪里坏处是当你抽屉组的最前端和最后段都有物品时,如若需要增加物品你只能把所有元素全部搬到更大的连续的抽屉组中,非常费力当然你也可以提前申请足够大的空间,但如若最后用不上那么多即是对空间的极度浪费。
??另外一种是离散地进行储存並且上一个抽屉储存着下一个抽屉的位置,即 当查看第 n 个抽屉的内容时就顺势直到第 n+1 个抽屉的位置在哪里了。这种存储结构的优势是你沒有前一种存储方式的顾虑可以随意在任意位置添加元素,删除第 n 个元素时只需将第 n-1 个抽屉记录第 n+1 个位置即可。但如若想知道第 n 个抽屜位置就需要 n-1 个抽屉的位置,以此类推需要全部遍历,效率比较低下不支持随机访问
??第一种就像是数据结构中的数组第二種就像是数据结构中的链表。如若经常需要从头遍历所有元素用链表会更好一些,但若经常需要随机访问元素则一般需要用数组。或鍺更一般地来说如果打算创建下来之后不会再修改其长度,就用数组否则用链表
??数组和链表还被用来实现其他数据结构比如 Facebook 實际使用的是什么呢?很可能是十多个数据库他们居于众多不同数据结构:散列表、B数等。数组和链表使这些更复杂的数据结构的基石

??每个递归算法都由两个不可或缺的部分组成:基线条件(base case)和递归条件(recursivecase)。递归条件指的是函数调用自己而基线条件则指的是函数不再调用自己,从而避免形成无限循环
??只要是数据结构,都有属于自己的操作例如数组和链表就有读取、插入、删除、修改等操作。而对于来说它的操作只有压入(push)弹出(pop)。当一个栈用于存储多个函数的变量时被称为调用栈。因为每当你调用函数时计算機都将函数调用所涉及的变量的值存储到内存中。当一个函数调用返回时就从栈的顶部弹出。
??使用栈虽然很方便但是也要付出代價:存储详尽的信息可能占用大量的内存。每个函数调用都要占用一定的内存如果栈很高,就意味着计算机存储了大量函数调用的信息在这种情况 下,你有两种选择一种是将递归化为循环解决,另一种是尾递归当然这就是另一个故事了。

??有时候你可能会遇到使用任何已知的算法都无法解决的问题。优秀的 算法学家遇到这种问题时不会就此放弃,而是尝试使用掌握的各种问题解决方法来找出解决方案分而治之(divide and conquer,D&C)是你学习的第一种通用的问题解决方法快速排序就是使用分而治之策略的一种优雅的排序算法。

D&C 思路是递归嘚使用 D&C 解决问题的过程包括两个步骤:

  1. 不断将问题分解(或者说缩小规模),直到符合基线条件

??编写涉及数组的递归函数时,基線条件通常是数组为空或只包含一个元素陷入困境时,有必要检查一下基线条件是不是这样的

??诸如 Haskell 等函数式编程语言没有循环,洇此你只能使用递归来编写类循环例如,函数 sum 可以这样编写

# 用函数式程序设计语言 Haskell 所编写的 sum 函数。 # 用循环编写 sum 函数

??归纳证明是┅种证明算法行之有效的证明方式。它分为基线条件和归纳条件在数学领域中被称为第一类数学归纳法。归纳证明常常与 D&C 协同发挥作用

??C语言标准库中的 qsort 函数实现的就是快速排序,是一种比选择排序快得多的排序算法快排的平均大 O 运行时间为 O(n*log n )。其基本步骤为:

  1. 数组嘚 pivot的选取
  2. 分别创建两个数组,其中包含除 pivot 外小于等于 pivot 的以及大于 pivot 的。
  3. 分别再对这两个数组进行快排

??快速排序的实际运行时间很夶程度上都由 pivot 决定,如果 pivot 一直选取数组第一个元素时它的栈的高度就为 n,每层的操作数也为 n最终的运行时间为 O(n^2^)。而如果每次都选取中間的元素时栈的高度就是 log n,每层的操作数还是 n

??散列表,又称哈希表(hash table)由散列函数和数组构成。任意一个可处理的输入数据经过散列函数后,可将输入数据映射到数组中某个位置的内存地址中内存地址又可以另外指向其它具体的数据,这个数据则被称作是散列值简称。充当的数据类型可以是任意类型而前面输入数据则被称作是,充当的数据类型只能是不可变类型 理想的散列函数能夠保证所有不同的键映射的内存地址互不相同。但正因为是理想所以现实情况中很难办到。当不同键映射到同一处内存地址时就会产苼冲突。要想化解冲突只需将数组这个位置的内存地址指向一个链表即可,之后在这个链表中存储各自想要储存的值即可如下图所示。

??但如果某个链表的所涉及的元素过多查找散列表的速度会比较慢,以至于在最糟情况时散列表的各种操作的运行时间都是 O(n)。想偠尽可能地避免冲突需要有较低的装填因子以及良好的散列函数,当然这就是另一个故事了

    • 储存电话号码和联系人似乎用散列表是比較好的,这是个简单例子不妨稍微谈一下高级话题,比如 DNS 解析(DNS resolution)访问像 这样的网站时,计算机要先将域名转换为 IP 地址,即 74.125.239.133转换的过程其實就是将网址映射到 IP 地址上去。因此用散列表的特性来做是极好的
    • 缓存是一种常用的加速方式,几乎任何的大型网站都会使用缓存而緩存的数据则会储存在散列表中。当你访问 Facebook 的网页时你会先接入他们的服务器,如果某个网页所有用户看到的都应该是一样的那就会將事先保存好的网页展示给你,就像是所有人的登陆界面一样否则服务器就对网页做些处理,将生成的网页展示给你比如你的个人空間。这就是缓存它能使用户更快地看到网页,也因此 Facebook 需要做的计算量更少
根据《算法图解》的作者所知道的算法中,图算法应该是最囿用的而广度优先搜索就是图算法的一种,它能够找出两样东西之间的最短距离

??像从旧金山双子峰到金门大桥的最少换成次数,戓者去你朋友家的最短路径再或者是国际象棋中把对方将杀死的最少步数。都被称为是最短路径问题

要解决最短路径问题通常需要两個步骤:

  1. 使用图来建立问题模型;
  2. 使用广度优先搜索解决问题。

??图用于模拟不同的东西是如何相连的它由节点组成,一个节点所直接指出去的所有节点统一称作是邻居


广度优先搜索是一种用于查找算法,它可以解决两类问题:

  1. 从节点 A 出发有通往节点 B 的路徑吗?
  2. 如果有那么从节点 A 出发,通往节点 B 的哪条路径最短

??以节点 A 为中心,节点 A 的邻居被称为是节点 A 的一度关系邻居的邻居被称為是二度关系,以此类推在广度优先搜索看来,一度关系胜过二度关系二度胜过三度,因此它会先在一度关系中查找节点 B一度没有僦找二度,二度没有就去三度直到找到为止或者所有的节点都遍历过一遍为止

??队列的工作原理与现实生活中的队列完全相同是┅种数据结构。它只支持两种操作即入队出队。Python 中可以从 cllections 库中引入 deque 函数来创建一个双端队列
??为了实现广度优先搜索算法,我们需要先实现图再去通过队列的先进先出的特性来实现算法。

??没有邻居的节点被称为是有向图互为邻居的节点被称为是无向图。像這样一个节点对应多个节点的结构像极了映射因此我们可以用散列表来储存图,将每个节点设为键每个节点的邻居设为值。

先用队列按照几度关系的顺序依次将节点入队具体步骤为:

  1. 将中心节点的邻居添加至队列中;
  2. 只要搜索队列不是空的,建立循环;

  3. 检查 P 有没有被檢查过

    1. 检查 P 是不是目标节点

      1. 如果是则返回 True
      2. 如果不是则将 P 的邻居添加到队列中

??在最糟糕的情况下你需要遍历整个图,也就是说每条嘟要走一次并且你需要对每个节点进行依次检查,于是时间复杂度为 O(V + E)其中 V(vertical)为节点数,E(eadg) 为边数

??如果说广度优先搜索是解决最短路徑问题,那么狄克斯特拉算法就是解决最快路径问题应用狄克斯特拉算法时,图中每条边都有与之相关联的数字这叫做权重。并且帶权重的图被称为是加权图,不带权重的图被称为时非加权图值得一提的是狄克斯特拉算法只适用于有向无环图无负权边的情况。

狄克斯特拉算法包含以下几个步骤:

  1. 设中心节点为 A列出如下表格;
    1. 找出所有节点中“耗时”最少的节点,在这里不妨设 α < β,因此我们很轻松地找出了节点 B
    2. 计算 A 到 B 每个邻居的“耗时”,若 结果 小于 原有结果则更新相应节点的“耗时”与“父节点”的值。
    3. 由于 B 的邻居都已哽新完毕因此 节点 B 不再参与下一轮的循环。直到所有节点的邻居更新完毕
  1. 根据目标节点的父节点,向前依次追踪节点直到某个节点嘚父节点为 中心节点 A,得出完整最短路线

Q:为什么算法实现的充分条件是有向无环图

A:若节点与节点之间相互成“环”那么每循环“环”一次总耗时就要无意义地增加,这样的路径不可能是最快路径

Q:为什么算法实现的充分条件是不存在负权边

A:若含有负权边那么在后续的循环中,有可能会更新之前已经淘汰掉的节点的“耗时”以及“父节点”的值如上述的 节点 B,这时理应要再对 节点 B 进行一佽检查可是由于 节点 B 已经淘汰掉了,因此无法更新 B 的邻居们所以可能会使真实结果实际演算结果产生不小的出入(其实就是贪心的鍋,导致只能求得近似解)狄克斯特拉算法看起来就像是出了 bug 一样。因此应对这种情况,我们必须换一个算法来实现——贝尔曼-福德 算法当然这就是另一个故事了。

??以表格作为算法的出发点需要用到三个散列表来装填三种数据,即 graph , parents , costs而其中 graph 还需要存储各个边的權重,因此需要再套一层散列表即 第一层 = 键 : 值 = 节点 : 第二层散列表,第二层 = 键 : 值 = 邻居 : 边的权重

? 贪心算法,又称贪婪算法即 每步都选擇的局部最优解,最后得到近似全局最优解或全局最优解采取的是一种步步为“赢”的策略手段。
??在一些问题中有时你不得不需偠计算出所有合法情况下的解。这种问题就被称作为 NP完全问题在每次计算出的解集中,从中选出最符合题意条件的解从而求得精确最優解。而往往这种暴力算法所带来的运行速度都是非常糟糕的这时需要采用贪心算法。虽然多数情况下只能求得近似解但时间复杂度偠比纯暴力计算好看得多。

NP完全问题模型—集合覆盖问题

??假设你办了个广播节目要让全美 50个州的听众都收听得到。为此你需要决萣在哪些广播台播出。在每个广播台播出都需要支付费用因此你力图在尽可能少的广播台播出。广播台的名单 demo 如下

??每个广播台都覆盖特定的区域,不同广播台的覆盖区域可能重叠而我们呢现在的问题是如何找出覆盖全美 50个州的最小广播台集合,这听起来很容易泹其实运算量极大,具体方法余下

  1. 列出每个可能的广播台集合,这被称为 幂集(power set)因此,可能的子集有 2^n^个(包括空集)
  2. 在这些 2^n^个子集中,选中覆盖全美 50个州的最小集合

??当然,n 在 0~10 的区间范围内还好说但当 n 超过了这个范围,实际操作数将急剧增加更为痛苦的是,目前没有任何算法可以足够快地解决这个问题这时就需要近似算法(approximation algorithm)解决类似的问题,具体方法如下

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

具体的 Python 代码实現如下。

stations = {} # 需要有可供选择的广播台清单使用散列表来表示它。

NP完全问题模型—旅行商问题

??有一位旅行商他需要前往 n个城市,同时保证旅程最短因此他需要考虑各种各样可能的顺序情况,而对于每种顺序他都要计算总旅程,再挑选出旅程最短的路线那么很明显,他需要考虑 n! 个顺序情况
??针对这种问题,当 n 比较大时可以采取贪婪算法,具体步骤为

  1. 去往离起点城市最近的城市,并将起点城市更新为该城市

??旅行商问题和集合覆盖问题有一些共同之处:你需要计算所有的解,并从中选出最小/最短的那个这两个问题都属於NP完全问题。
??通常来说用 贪婪算法 解决一个 NP完全问题并不难,而真正难的部分则是意识到这是个 NP完全问题下面列出几个判断 NP完全問题的经验性规律。

元素较少时算法的运行速度非常快但随着元素数量的增加,速度会变得非常慢

  • 涉及“所有组合”的问题通常是NP完铨问题。
  • 不能将问题分成小问题必须考虑各种可能的情况。这可能是NP完全问题
  • 如果问题涉及序列(如旅行商问题中的城市序列)且难鉯解决,它可能就是NP完全问题
  • 如果问题涉及集合(如广播台集合)且难以解决,它可能就是NP完全问题
  • 如果问题可转换为集合覆盖问题戓旅行商问题,那它肯定是NP完全问题
??动态规划相较于其它算法来说,是属于比较重要但同时也比较麻烦的一种算法。因此这里先叻解一个例子再根据这个例子具体说明可能会好理解一点

??假设你现在是一个不折不扣的小偷,晚上进商城准备偷东西你的背包很鉮奇,它装东西本领只和这个东西的重量有关不妨限定你的背包最多只能装 4kg的东西。下面是你想偷的东西的清单每件商品只有一个。

??你的目标很明确在有限的容量里装入尽可能多的有价值的物品。因为你明白这其中要满足某种配比才有可能是问题的最优解(比如拿走一个 笔记本电脑 和一个 IPhone 才可能是最赚的),但你不确定因此,你掏出纸和笔打算写一个动态规划网格我承认这可能很突然,但先照着做一下

??其中,网格的各行为商品各列为不同容量(1~4kg)的背包。首先要声明的是待会儿要填满这里所有的单元格,因为它們将帮助你计算背包的最大价值你要做的事情是:逐行填写,填完一行再填下一行填 a 行 b 列时,你假定现在只能偷 小于等于 a 行 的商品苴你的背包大小只有 b kg。举个例子当你填 第二行 第三列 的单元格时,你只能偷 吉他 以及 音响并且你的背包容量只有 3kg,这时将所能带走的朂大价值填入所对应的单元格中

??看完上面有点懵是正常的,觉得意义不明也有可能因此需要适当“放”出来一点东西出来缓和以丅。
??动态规划讲究将原问题划分为 n 个子问题所以我们才将背包容量这个限制条件划分成 4 大块。通过解决第 1 个子问题保存结果,接著解决第 2 个子问题时可以调用之前的结果类似于尾递归。因此填表的时候沿着一列往下走时最大价值不可能降低。因为每次迭代时伱都存储了当前的最大价值,最大价值不可能比之前还要低
??值得一提的是,这 n 个子问题之间必须是相互独立且离散的拿背包问题舉例,如果拿了笔记本电脑之后再拿 IPhone 时电脑会爆炸简言之就是电脑的价值会受手机的影响,这样的情况是用不了动态规划的
每个单元格的价值 = 上一个单元格的价值 与 当前商品的价值 + 剩余空间的价值 的两者的较大值
??按照上述公式所填写的完整的表格如下其中最大價值为¥4000,也就是说当你的容量只有 4kg 的背包装一个 IPhone 和一个笔记本电脑时,收益才能达到最大化

??在背包问题中,任意调换某两行都鈈会影响最终结果甚至逐列填写单元格也没关系,但在其它动态规划模型中就不一定成立了你也可以在最后一行添加一个任意一个商品而不影响上面的计算结果,当然前提是这件商品的重量是个整数如果不是整数则要重新划分价格区间。

  1. 需要在给定约束条件优化某種指标时例如在背包问题中,你必须在背包容量给定的情况下拿到价值最高的商品。
  2. 问题可分解为离散的子问题时
  1. 每种动态规划解決方案都涉及网络
  2. 单元格中的值通常就是你要优化的值在背包问题中,单元格的值为商品的价值
  3. 每个单元格都是一个子问题,因此伱该考虑如何将问题分成子问题这有助于你找出网格坐标轴。
  4. 没有放之四海而皆准的计算动态规划解决方案的公式

遇到动态规划问题時首先要问自己这么几个问题:

  1. 单元格中的值是什么?或者说 在动态规划中你要将哪个指标最大化
  2. 如何将这个问题划分为子问题
  3. 应該使用什么样的公式来填充每个单元格?

??动态规划实际上比较棘手的部分就是对动态规划问题的建模这一块但有时你就是不确定具體到底该怎么做。这时计算机科学家会开玩笑说:不妨就使用费曼算法(Feynman algorithm)。这个算法是以著名物理学家 理查德·费曼 命名的算法具體步骤如下。

??由此我们知道有些算法并非精确的解决步骤,而是会帮助你理清思路的框架本质还是一种工序上的优化问题。

??接下来我们再来讨论三个动态规划问题其中第一个和背包问题类似,其余两种则需要重新建模

??加入你要去伦敦度假,假期两天泹你想去游览的地方有很多。由于你没法前往每个地方游览因此如何在有限的时间内,游览地方的评分总和最高是你的目标具体行程洳下。

根据上面的清单以及背包问题的公式我们可以非常轻松地填满如下表格。

??有必要提前声明的是最长公共子串讲究的是字符の间的连续性的,即 绝对顺序相反,最长公共子序列讲究的是字符之间的相对顺序举个例子,fosh 和 fish 的最长公共子串的长度为 2最长公共孓序列的长度为 3。fosh 和 fort 的最长公共子串的长度也是 2但最长公共子序列的长度只有 2。

??FISH 和 HISH 的最长公共子串的长度为多少相信我们都可以┅眼看出来,但对于计算机来说是要设计专门的算法来处理这样的问题的
??首先判断这本质上应该是个动态规划问题,毫无疑问这些个单词都可以分为单个离散的字符。并且对于 FISH 来说 HISH 本身就是约束条件,反过来也一样所要优化的指标当然也就是两者的 公共子串的長度。

根据以上分析判断这是个动态规划问题之后直接上网格表

??针对单元格中索要填入的的值,思考公式是什么再次强调一下,公式只是表象其内部还是子问题的保存和调用的一个尾递归。

  1. 如果两个字母不相同时值 = 0。
  2. 如果两个字母相同时值 = 左上角单元格的值 + 1。

实现这个公式的伪代码类似于下面这样

根据公式不难填满得到如下表格。

0 0 0 0
0 0 0
0 0 0
0 0 0

同理HISH 和 VISTA 的最长公共子串如下。

0 0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0 0

需要注意的是最终的答案並不总在最后一个单元格中。

同样利用上面的分析方法,也可以得到动态规划最长公共子序列的公式

  1. 如果两个字母不同,就选择上方囷左边的单元格的值较大的哪个
  2. 如果两个字母相同,就将当前单元格的值设置为左上方的单元格的值加 1

求 FOSH 和 FORT 的最长公共子序列的长度嘚网格如下。

求 FOSH 和 FISH 的最长公共子序列的长度的网格如下

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

??如仩图,现在桌子上有一个水果现在它只可能是橙子或者柚子中的一种,你不能直接问卖水果的人手头上已知的条件是:柚子通常比橙孓更大、更红。现在的问题是它最有可能是橙子还是柚子

??不妨在脑内想象一个这么样的图表,其中 O 为橙子G 为柚子,横坐标为大小纵坐标为颜色的深浅。注意到坐标轴是连续的,而水果则抽象成了一些离散的点或者说向量。
??那么如何大致判断这个神秘的水鍋到底是什么呢其实非常简单,不妨找一下离 神秘水果所表示的点 最近的三个水果然后比较以下那种水果的种类更多即可。若假定 3个沝果中有两个都是橙子,那么这个神秘水果很有可能就是橙子

??在判断那个水果的种类的过程中,其实已经使用了 K最近邻(k-nearest neighbours, KNN)算法利用自然语言描述刚刚的 KNN算法过程如下。

  1. 需要对一个水果进行分类
  2. 查看它 K个最近的邻居。
  3. 在这些邻居中橙子多余柚子,因此它很可能是橙子

??要对东西进行分类时,可以首先考虑采用 KNN算法你可以使用 KNN 来做两项基本工作——分类回归(regression)

抽取特征时要挑准匼适的特征。

  1. 抓准与之紧密相关的特征;
  2. 不偏不倚的特征(例如如果只让用户给喜剧片打分,就无法判断它们是否喜欢动作片)

??茬前面的水果示例中,你根据个头和颜色来比较水果换言之,你比较的特征是个头和颜色现在假设有三个水果,你可抽取它们的特征很明显,A 和 B 直观看起来十分相似但事实上具体多少相似我们还是可以通过 KNN算法 来解决。

??横坐标表示 个头纵坐标表示 红的程度,洇此我们可以把这三个点用坐标表示出来。

??再利用毕达哥拉斯公式不难算出每两点之间空间距离并标在图表上。因为 A 与 B 两点之间嘚距离最短因此它们俩是最像的,这也印证了之间的直觉

??假定你在你的老家卖冰棍,由于是夏天卖地比较火,因此每天都要进貨一些新的冰棍每天的进货量由下面几个指标进行预测。

  1. 天气指数 1~5(数字越大 代表 气温越高);
  2. 是否是周末或节假日(周末或节假日为 1否则为 0);
  3. 有无活动(有为 1,否则为 0)

??之后,你测了 1个月的数据记录了在各种不同的日子里卖出的冰棍数量。在这 30天的容量中你选出 6天的数据作为样本,如下表所示

??今天是周末,气温比较高店里也没有办什么活动,点坐标为(4,1,0)根据以上数据,你要預测今天大概能卖出去多少根冰棍只要学过高中数学,就知道这就是个典型的回归问题但有稍微有点不一样。由于之前说过 KNN算法就是鼡来解决编组回归问题的因此我们要用 KNN算法来解决。

利用毕达哥拉斯公式可以算出“今天”与A,B,C,D,E,F点之间的距离如下所示。

??K 取 4 时與(4,1,0)最近的邻居为 A、B、D 和 E。将这些天售出的冰棍数平均结果为 218.75。这就是回归(regression)

??前面计算两位用户的距离时,使用的都是距离公式但在实际工作中,则经常会使用余弦相似度(cosine similarity)来量化两位用户的相似程度余弦相似度不计算两个矢量的距离,而比较它们角度如果要深入研究,那就是另一个话题了

??到这里不妨试着猜想一下开头提及的原理。网易云首先为每个注册的用户生成一个用户画潒(Persona)即 将用户的每个具体信息抽象成标签,利用这些标签将用户形象具体化从而为用户提供有针对性的服务。其中将每个具体信息抽象成标签的过程可能就要用到 K最近邻算法不过这里的空间维数可能要达到千以上的数量级,并且每一维都有各自的权重同理,哔哩嗶哩也可能采用这样机制
??但哔哩哔哩和网易云音乐可能没有直接的关系。不妨假定在网易云音乐中用户A 与 用户B 之间的标签十分相姒。相似到什么程度呢一旦 A “喜欢”了一首歌,就会立即反映到当天 B 的推荐歌曲中接下来的说法要建立在一个前提之上,就是 这种类型的歌曲的听众 可以映射到 哔哩哔哩 的一个较小的“圈子”中比如,喜欢听 二刺螈 的曲子的人 在哔哩哔哩中可能是混“番剧”这个圈子嘚那么就有这种可能,十月新番 在 哔哩哔哩 准时开播假定 番剧 和 OP 是同时上架的,A 第一时间追了一集之后马上去网易云音乐对 OP 点了“喜歡”在这之后,B 也追完了无意打开网易云发现首页上竟然有 自己正在追的动画的 OP,于是在曲子的评论中不禁如下感叹(当然这不是峩,废话

??KNN算法在神奇的机器学习领域也占有一定的比重。机器学习皆在让计算机更聪明创建推荐系统,就是个机器学习的例子

??OCR 指的是光学字符识别(optical character recognition),这意味着你可拍摄印刷页面的照片计算机将自动识别出其中的文字。Google使用OCR来实现图书数字化OCR是如何笁作的呢?我们来看一个例子请看下面的数字。

如何自动识别出这个数字是什么呢我们当然可以使用 KNN。

  1. 浏览大量的数字图像将这些數字的特征提取出来。这在机器学习中被称之为训练(training)
  2. 遇到新图像时,提取该图像的特征再找出它最近的邻居都是谁。

??与前面嘚水果示例相比OCR 中的特征提取明显要复杂得多得多,但再复杂的技术也是基于 KNN 等简单理念的而这些理念也可用于语音识别和人脸识别。当你将照片你上传到 Facebook 时它有时候能够自动标出照片中的任务,这正是机器学习在发挥作用

??垃圾邮件过滤器用的并非 KNN 算法,而是叧一种基本算法——朴素贝叶斯分类器(Naive Bayes classifier)大多数机器学习算法都包括训练的步骤:要让计算机完成任务,必须先训练它垃圾邮件过濾器也不再例外,因此你需要使用一定量的数据对这个分类器进行训练垃圾邮件过滤器可以计算出一个任意一个邮件为垃圾邮件的概率,其应用领域与 KNN ??你甚至还可以用朴素贝叶斯分类器对之前提到的水果进行分类:假设有一个又红又大的水果它是柚子的概率是多少呢?……

未来很难预测由于涉及的变量太多,这几乎是不可能完成的任务

??每当用户登录自己的 B 站 账号时,都要从庞大的数据中去查找并判断是否存在这样 ID。倘若你要设计 B 站 用户的登陆系统你会选择什么样的数据结构来存储用户 ID 以及 算法用来查找 ID。
??如果使用②分查找并使用极其庞大的数组来存储数据,那么注销和注册一个 ID 将是个极其麻烦的工作为此,有人设计了一种名为二叉查找树(binary search tree)嘚数据结构来减轻算法的负担。

??二叉查找树类似于上面这样这种数据结构形象地表示出来之后长相酷似“树”,因此命名为二叉查找树其实是一种变异的“链表”。也拜这种结构所赐使得数据的增删变得极其地方便。其中树的最顶端被称为根节点,其余节点被称为子节点对于其中每个节点,左子节点的值都比它小右子节点的值都比它大。
??对于树的查找其原理与二分查找相似,因此平均时间复杂度都为 O(log n)举个例子,假设我要在上面 5个数据中查找“Maggie”为此,我首先检查根节点是否为“Maggie”发现匹配失败之后,发现“Maggie”应该排在“David”的后面因此我往右边找。“Maggie”应该排在“Manning”前面于是接着往左边找,最终找到了“Maggie”
??与其它大部分数据结构鈈同的是,树自己本身是存在优劣的即 有好的“树”,也有“坏”的树一颗树中两个分叉的子树数量比例越高,树的性能就越佳

??第一棵树正在处于平衡状态,此时的最糟的运行时间为 O(log n)第二棵树处于非平衡状态,此时的最遭的运行时间为 O(n)仿佛整棵树马上就要向咗倒下来。由于树与链表相似都不支持随机访问,二叉查找树处于平衡状态时平均访问时间为 O(log n)。

下面给出一下数组和二叉查找树的性能

??此外,还有几种特殊的二叉查找树如 B树红黑树伸展树 等,当然这就是另一个故事了

这里非常简单地说说搜索引擎的笁作原理。假设你有三个网页内容如下。

我们根据这些内容船舰一个散列表

??这个散列表的键为单词,值为包含指定单词的页面現在假设有用户搜索 hi,在这种情况下搜索引擎需要检查哪些页面包含 hi。
??搜索引擎发现页面A和B包含hi因此将这些页面作为搜索结果呈現给用户。现在假设用户搜索 there你知道,页面 A 和 C 包含它非常简单,不是吗这是一种很有用的数据结构:一个散列表,将单词映射到包含它的页面这种数据结构被称为反向索引(inverted index),常用于创建搜索引擎如果对搜索感兴趣,从反向索引着手研究是不错的选择

??绝妙、优雅且应用广泛的算法少之又少,傅里叶变换算是一个Better Explained 是一个杰出的网站,致力于以通俗易懂的语言阐释数学它就傅里叶变换做叻一个绝佳的比喻:给它一杯冰沙,它能告诉你其中包含哪些成分换言之,给定一首歌曲傅里叶变换能够将其中的各种频率分离出来。
??这种理念虽然简单应用却极其广泛。例如如果能够将歌曲分解为不同的频率,就可强化你关心的部分如强化低音并隐藏高音。傅里叶变换非常适合用于处理信号可使用它来压缩音乐。为此首先需要将音频文件分解为音符。傅里叶变换能够准确地指出各个音苻对整个歌曲的贡献让你能够将不重要的音符删除。这就是MP3格式的工作原理
??数字信号并非只有音乐一种类型。JPG也是一种压缩格式也采用了刚才说的工作原理。傅里叶变换还被用来地震预测和DNA分析
??使用傅里叶变换可创建类似于 Shazam 这样的音乐识别软件。傅里叶变換的用途极其广泛你遇到它的可能性极高。

接下来的三个主题都与可扩展性和海量数据处理相关

??我们身处一个处理器速度越来越赽的时代,如果你要提高算法的速度可等上几个月,届时计算机本身的速度就会更快但这个时代已接近尾声,因此笔记本电脑和台式機转而采用多核处理器为提高算法的速度,你需要让它们能够在多个内核中并行地执行!
??来看一个简单的例子在最佳情况下,排序算法的速度大致为 O(n log n)众所周知,对数组进行排序时除非使用并行算法,否则运行时间不可能为O(n)对数组进行排序时,快速排序的并行蝂本所需的时间为 O(n)
??并行算法设计起来很难,要确保它们能够正确地工作并实现期望的速度提升也很难有一点是确定的,那就是速喥的提升并非线性的因此即便你的笔记本电脑装备了两个而不是一个内核,算法的速度也不可能提高一倍其中的原因有两个。

  • 并行性管理开销假设你要对一个包含1000个元素的数组进行排序,如何在两个内核之间分配这项任务呢如果让每个内核对其中500个元素进行排序,洅将两个排好序的数组合并成一个有序数组那么合并也是需要时间的。
  • 负载均衡假设你需要完成 10个任务,因此你给每个内核都分配5个任务但分配给内核A的任务都很容易,10秒钟就完成了而分配给内核B的任务都很难,1分钟才完成这意味着有那么 50秒,内核B在忙死忙活洏内核A却闲得很!你如何均匀地分配工作,让两个内核都一样忙呢

??有一种特殊的并行算法正越来越流行,它就是分布式算法在并荇算法只需两到四个内核时,完全可以在笔记本电脑上运行它但如果需要数百个内核呢?在这种情况下可让算法在多台计算机上运行。MapReduce 是一种流行的分布式算法你可通过流行的开源工具 Apache Hadoop 来使用它。

??假设你有一个数据库表包含数十亿乃至数万亿行,需要对其执行複杂的SQL查询在这种情况下,你不能使用MySQL因为数据表的行数超过数十亿后,它处理起来将很吃力相反,你需要通过Hadoop来使用MapReduce!
??又假設你需要处理一个很长的清单其中包含 100万个职位,而每个职位处理起来需要 10秒如果使用一台计算机来处理,将耗时数月!如果使用 100台計算机来处理可能几天就能完工。
??分布式算法非常适合用于在短时间内完成海量工作其中的MapReduce基于两个简单的理念:映射(map)函数和归並(reduce)函数。MapReduce使用这两个简单概念在多台计算机上执行数据查询数据集很大,包含数十亿行时使用 MapReduce 只需几分钟就可获得查询结果,而传统數据库可能要耗费数小时

??在假设你管理着 Google,要避免将用户重定向到恶意网站你有一个清单,其中记录了恶意网站的 URL你需要确定偠将用户重定向到的 URL 是否在这个清单中。这些一类型的问题通常都要涉及庞大的集合。给定一个元素你需要判断它是否包含在这个集匼中。为快速做出这种判断可使用散列表。例如Google可能有一个庞大的散列表,其中的键是已搜集的网页
??初始状态时,所有键所对應的值都是“False”第一次判断 A 网页是否在该集合时,只需或许 A 网页所对应的值即可随后发现不在这个集合,同时 A 的确是个恶意网页时僦将 “False” 改为 “True”,之后系统再次判断 A 网页是否是恶意网页时可以先获取其对应的的值即可。散列表的平均查找时间为 O(1)即查找时间是凅定的,这应该是个非常乐观的时间复杂度了不过 Google 需要建立数万亿个网页的索引,因此这个散列表非常大需要占用大量的存储空间。媔临海量数据我们可以选择非常有创造性的方案——布隆过滤器,来解决这种问题

??布隆过滤器提供了解决之道。布隆过滤器是一種概率型数据结构它提供的答案有可能不对,但很可能是正确的为判断网页以前是否已搜集,可不使用散列表而使用布隆过滤器。使用散列表时答案绝对可靠,而使用布隆过滤器时答案却是很可能是正确的。具体表现为如下

  1. 可能出现错报的情况,即 Google 可能指出“這个网站已搜集”但实际上并没有搜集。
  2. 不可能出现漏报的情况即如果布隆过滤器说“这个网站未搜集”,就肯定未搜集

??布隆過滤器的优点在于占用的存储空间很少。使用散列表时必须存储 Google 搜集过的所有 URL,但使用布隆过滤器时不用这样做布隆过滤器非常适合鼡于不要求答案绝对准确的情况。

??HyperLogLog 是一种类似于布隆过滤器的算法HyperLogLog近似地计算集合中不同的元素数,与布隆过滤器一样它不能给絀准确的答案,但也八九不离十而占用的内存空间却少得多。面临海量数据且只要求答案八九不离十时完全可以考虑使用概率型算法

接下来的两个话题都与加密算法有关

??之前介绍的散列函数都是将直接映射到内存地址上。而另一种散列函数安全散列算法(secure hash algorithm,SHA)函数则是将字符串类型直接映射到一个较短字符串上。比如 "hello" 这个字符串通过 SHA256

下面简述安全散列算法的安全体现在哪里

  1. 这个散列函数不会产生冲突,因此不会出现因为明明输错密码还能够成功登录的情况
  2. 这个散列函数没有反函数,意味着不能直接反破译出密码因此密码校验都是用 SHA 加密结果进行比对。
  3. 就算原字符串只改变了一个字符最终的 SHA 结果也会截然不同。因此攻击者无法通过比较散列值昰否类似来破解密码这时就称这种散列函数对全部敏感

??SHA除了核对密码外还可以判断文件是否为同一文件,即 将两个文件的 SHA 值计算出来进行比对即可

??SHA实际上是一系列算法:SHA-0 , SHA-1 , SHA-2 和 SHA-3。其中SHA-0 和 SHA-1 已被发现存在一些缺陷。如果你要用SHA算法来计算密码的散列值请使用 SHA-2 或 SHA-3。当前最安全的密码散列函数是bcrypt,但没有任何东西是万无一失的

??simhash 是对局部敏感的散列函数,表现为如果你对字符串做细微的修改Simhash 生成的散列值也只存在细微的差别。这时你可以通过比较散列值来判断两个字符串的相似程度。

  • 老师们可以使用 Simhash 来判断学生的论文是否是从网上抄的

??简单的加密算法就不再赘述了,因为加密程度比较低因此非常容易暴力破解出来。Diffile-Hellman 算法简称 DH 算法。它有以下两個优点

  1. 双方无需知道加密算法。他们不必会面协商要使用的加密算法
  2. 要破解加密的消息比登天还难。

??DH 算法加密时会使用到两种密鑰:公钥和私钥顾名思义,公钥就是公开使用的密钥被第三者获取了也无所谓。而私钥则是最终解密的关键。具体 DH 算法是如何执行嘚可以去 B 站搜索 av,这个视频中用类比的方式比较直观地演示了密钥交换过程个人也觉得既优雅又不难理解。DH 算法是算法加密的先驱者它的后辈 RSA 算法依然在被广泛使用,当然这就是另一个故事了

??但愿读者还能想起来自己高中还确实学过线性规划这么个东西。线性規划就是为了不断优化最终达到最优解的工具,这与算法中优化的思想不谋而合因此线性规划本质上也是可以算作是算法。所有的图算法都可使用线性规划来实现线性规划是一个宽泛得多的框架,而图问题只是其中的一个子集!因此把如此牛掰的算法放最后讲也不是沒有道理的线性规划使用 Simplex 算法,不过这个算法很复杂详细介绍就又称另一个故事了。

??这是我在思否落地的第一篇技术博文首先感谢思否给予像我一样的平凡人记录自己所学的机会。国内像思否的博客系统有很多家但我觉得都没有思否酷,所以最终就选择了思否
??可能会说你一个刚入坑的小屁孩写这种没水平的技术博客不是笑话吗(也许并没有人问,谁会看菜鸡写的博文呢大概连喷都懒得喷吧)。Well,I can't even agree more.目前我写博文的目的只是为了产出一味的输入而没有输出只会把自己变成书呆子。趁还是学生阶段利用好周边富余的学习资源,通过写博文消化的同时还能复现何乐而不为呢。
??希望你可以在这个饱受争议的领域中走出那个连曾经那个自己都不敢想象的路途,浮躁的情绪沉淀下来或成为你的决心希望我可以一直娓娓道来曾经我还未讲述的故事,当然这就是另一个故事了


}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信