程序 = 数据结构 + 算法 程序员
—— 图灵奖得主,计算机科学家N.Wirth(沃斯)面试
进入 BAT 这样的巨头企业工做,无疑是不少程序员的梦想。但事实上,能经过这些公司高难度编程面试的只是一小撮人。算法
做为程序员,咱们作机器学习也好,作Python开发也好,Java开发也好。chrome
有一种对全部程序员无一例外的刚需 —— 算法与数据结构数据库
平常增删改查 + 粘贴复制 + 搜索引擎能够实现不少东西。编程
一样,这样也是没有任何竞争力的。数组
咱们只能够粘贴复制类似度极高的功能,稍复杂的逻辑没有任何办法。网络
语言有不少,开发框架更是突飞猛进3个月不学就落后。数据结构
咱们能够学习不少语言,不少框架,但招聘不会考你用5种语言10种框架实现同一个功能。框架
真正让程序员有区分度,企业招聘万年不变的重点 —— 算法与数据结构。
今天小七给你们介绍的就是面试当中很是实用的两个数据结构,面试当中一提,秒变编程老司机。
前缀树(prefix trie)
前缀树是一种数据结构,容许你经过其前缀快速查找字符串,还能够查找有公共前缀的字符串。
我对介绍这一数据结构的第一条建议是,将它称为“前缀树”,而不只仅是“树”。
这样,你就让面试官知道你是那种了解与前缀和后缀相关算法的人,而且你也但愿对你的fancy数据结构进行准确描述。
后缀树也是一个很是有趣的话题,但实现细节十分残暴。这就是为何我只是谈论前缀树,而且伪装了解后缀树。
谁会真的用前缀树?
基因组学研究人员!
事实证实,现代基因组研究在很大程度上依赖于字符串算法和数据结构,由于你试图从组成基因组序列的数百万个核苷酸中探索奥秘。
对于基因组数据,你常常须要对齐序列,找到差别或找到重复的模式。若是你想了解更多相关信息,能够先阅读生物信息学读物,而后参与“DNA测序算法”或“生物信息学算法”等课程。
若是你想要阅读一些真正有意思的读物,我强烈建议你读一读药物基因组学。随着基因组测序和字符串算法的进步,咱们实际上能够预测使用个体的基因组,来肯定它们是否具备对药物正确反应的正确基因。
例如,若是他们的基因组缺乏用于产生处理某种药物的酶的基因,那么药物可能会对他们产生反作用。若是咱们知道什么基因是重要的,咱们能够给他们一种不一样的药物!
我认可,前缀树和基因组学之间的联系不太紧密。其实前缀树的最直接用法就是用来查字典啦!但光这么讲不是忒无聊了点么。
前缀树的原理
想象一下,你有一棵树,每一个节点都有一个包含26个子节点的数组,每一个子节点对应一个英文字母。(若是要包含其余字符,能够将26更改成不一样的值。)要在你的树中表示单词,你将从根节点开始,沿着路径向下走,并在每一个节点添加一个字母。
例如:对于“tea”这个词,你从根开始,被引导到t节点,而后是e,最后是a。所以,搜索单词须要O(N)的时间(其中N是单词的长度),若是单词的前缀不存在,则能够提早结束。若是我查询“zzzzzzzz”,树能够在“zz”以后结束查询。
布隆过滤器
布隆过滤器是集合的几率版本。检测集合是否包含某元素的时间复杂度为O(1)、空间复杂度为O(N)。
Bloom过滤器也能够检测出集合是否可能包含该元素,它的时间复杂度为O(1),而空间复杂度只须要O(1)!
谁会真正使用布隆过滤器?
Chrome须要在不牺牲速度或空间的状况下保护你免受访问垃圾邮件网站。
想象一下,若是每次你点击一个连接,Chrome都必须进行网络通话来检查它庞大的垃圾邮件URL数据库,而后才容许你访问这个页面,这会不会让你等疯掉。
此外,设想一下,若是Chrome改善延迟的解决方案是在本地存储整个垃圾邮件URL列表,这根本就是不可行的!
因此,chrome在本地存储了一个潜在垃圾邮件URL的布隆过滤器,这既节省时间又节省空间,能够快速检查给定的URL是否为垃圾邮件。
对于普通的URL,布隆过滤器对“非垃圾邮件”的响应就足够断定了。
若是一个URL被标记为“多是垃圾邮件”,那么Google能够在跳转以前检查它真实数据库。
事实证实,当你愿意牺牲绝对时,你能够作出伟大的事情!
布隆过滤器的原理
大体作个介绍:
若是你想在Bloom过滤器中插入一个元素,首先假设有N个不一样的肯定性哈希函数。当同一个元素输入不一样哈希函数时,会获得不一样的值(冲突是能够有的)。
使用每一个哈希函数的输出做为数组的索引[注释1,注释2],并对应每一个索引i将数组[i]设置为true。插入元素就完成了!插入元素的时间复杂度是O(1),由于对每一个插入元素所作的惟一工做是运行恒定数量的哈希函数,并设置恒定数量的数组索引。
那该如何检查布隆过滤器是否包含该元素? 再次运行全部相同的哈希函数!
哈希函数是肯定性的,所以相同的输入应返回相同的输出。因此相对应每一个索引,检查布隆过滤器的数组是否在该索引处设置为true便可。
若是哈希函数输出的数组的每一个单元都为真,那么能够很高的几率说这个元素已经插入到了布隆过滤器中。这一方法老是存在误报的可能性。
不过,布隆过滤器的一大特点是永远不会出现漏报。
注释1:如何使用哈希函数的输出做为索引:设哈希函数输出整数值M,取长度N。N%M(N mod M)获得一个值Q,即0≤Q<M。这是一种取任意值并在一个范围内均匀分布的简便方法。
若是你之前没有遇到过这个问题,那么应该阅读关于mod运算符的内容,绘制一些示例数组,并使用M的不一样值进行实验,以了解N%M的效果。
注释2:实际上,你应该使用位数组而不是普通数组。数组的每一个元素至少须要1个字节,而你只须要为“数组”的每一个元素存储true / false。
所以,你能够经过将其存储为位数组来节省空间,这是这个数据结构的重点。
若是你想要听起来很聪明,那么位数组(也就是位向量)也值得你在面试时提出。嗯,真正的面试专家建议老是在脚注中。
注释3:严格来讲,若是你的全部哈希函数都在O(1)时间内运行,那么插入的复杂度才是O(1)。