介紹兩個面試神器

程序 = 數據結構 + 算法 程序員

 

—— 圖靈獎得主,計算機科學家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)。

相關文章
相關標籤/搜索