想當資深工程師?你需要熟悉這 3 種資料結構

【為什麼我們要挑選這篇文章】很多想當工程師的人都會學程式,但只會程式的工程師只能當碼農,負責調整既有的程式碼、維護系統等等。若要更上一層樓,工程師需要熟悉演算法和資料結構,它們是程式背後的邏輯思考架構。下文作者要跟工程師分享 3 個重要的資料結構。(責任編輯:郭家宏)

「《科技報橘》徵才中!跟我們一起定位台灣產業創新力 >> 詳細職缺訊息
快將你的履歷自傳寄至 [email protected]

又要面試啦!

工程師面試時該表現什麼?當然是你淵博的電腦知識,以及聰明的腦袋瓜。

如果你學富五車,上知深度學習,下知財務會計,那短短幾小時也絶不夠你表演。所以,你一定得知道面試官的套路,隨口丟出幾個應景的「冷知識」。

如果你基礎不行,三天前才練了幾條程式碼,那就更得準備幾個小把戲,不用打腫臉也能充個胖子。

基於這兩個需求,今天文摘菌(本文作者)就來介紹三個資料結構,讓你撐撐面試場面。

這三個資料結構就是:

1. 布隆過濾器(bloom filter)
2. 前綴樹(prefix trie)
3. 環形緩衝區(ring buffer)

先來說一下,為什麼挑這三個資料結構。

首先我覺得,你提到的資料結構要稍微冷門一些,這樣別人就會認為你瞭解很多不同類型的資料結構。但它不能太冷門,以免你的面試官要求你真正解釋實現細節或原理,那時你就 game over 了。最好是你提到的資料結構有點冷門,但你的面試官聽說過,對它有印象。

面試官都希望自己什麼都知道,他們聽說過這種資料結構但又不太瞭解,當你向他們介紹時,他們就會覺得你懂得特別多。

除此之外,這些資料結構還應該具有實際用例,以便在技術面試的時候,你能有機會展開介紹。它雖然稍微有點冷門但也不能太 low,你如果只知道一些菜鳥水平的資料結構(比如雙向連結串列),你的面試就掰了。

所以,這三個資料結構就被完美選中啦!

布隆過濾器(bloom filter)

布隆過濾器是集合的機率版本。檢測集合是否包含某元素的時間複雜度為 O(1)、空間複雜度為 O(N)。Bloom 過濾器也可以檢測出集合是否可能包含該元素,它的時間複雜度為 O(1),而空間複雜度只需要 O(1)!

誰會真正使用布隆過濾器?

Chrome 需要在不犧牲速度或空間的情況下保護你免受訪問垃圾郵件網站。

想像一下,如果每次你點擊一個連結,Chrome 都必須進行網絡通話來檢查它龐大的垃圾郵件 URL 資料庫,然後才允許你訪問這個頁面,這會不會讓你等瘋掉。此外,設想一下,如果 Chrome 改善延遲的解決方案是在本地儲存整個垃圾郵件 URL 列表,這根本就是不可行的!

所以,chrome 在本地儲存了一個潛在垃圾郵件 URL 的布隆過濾器,這既節省時間又節省空間,可以快速檢查給定的 URL 是否為垃圾郵件。對於普通的 URL,布隆過濾器對「非垃圾郵件」的響應就足夠判定了。如果一個 URL 被標記為「可能是垃圾郵件」,那麼 Google 可以在跳轉之前檢查它真實資料庫。事實證明,當你願意犧牲絶對時,你可以做出偉大的事情!

布隆過濾器的原理

布隆過濾器的維基百科頁用大量的術語描述了實現細節,所以在這裡我會用簡單的描述一下實現過程。如果你想要更精確的細節,你應該去看看維基百科。我會略過很多步驟,但我會讓你有一個大致瞭解。

如果你想在 Bloom 過濾器中插入一個元素,首先假設有 N 個不同的確定性雜湊函式(Hash function)。當同一個元素輸入不同雜湊函式時,會得到不同的值(衝突是可以有的)。

使用每個雜湊函式的輸出作為數組的索引 [註釋 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)。

前綴樹(prefix trie)

前綴樹是一種資料結構,允許你透過其首碼快速查找字元串,還可以查找有公共首碼的字元串。

我對介紹這一資料結構的第一條建議是,將它稱為「前綴樹」,而不僅僅是「樹」。這樣,你就讓面試官知道你是那種了解與首碼和尾碼相關演算法的人,並且你也希望對你的 fancy 資料結構進行準確描述。後綴樹也是一個非常有趣的話題,但實現細節十分殘暴。這就是為什麼我只是談論前綴樹,並且假裝瞭解後綴樹。

誰會真的用前綴樹?

基因組學研究人員!

事實證明,現代基因組研究在很大程度上依賴於字元串算法和資料結構,因為你試圖從組成基因組序列的數百萬個核苷酸中探索奧秘。對於基因組數據,你經常需要對齊序列,找到差異或找到重複的模式。如果你想瞭解更多相關信息,可以先閲讀生物訊息學讀物,然後參與「DNA 測序演算法」或「生物訊息學演算法」等課程。

如果你想要閲讀一些真正有意思的讀物,我強烈建議你讀一讀藥物基因組學。隨著基因組測序和字元串演算法的進步,我們實際上可以預測使用個體的基因組,來確定它們是否具有對藥物正確反應的正確基因。例如,如果他們的基因組缺少用於產生處理某種藥物的酶的基因,那麼藥物可能會對他們產生副作用。如果我們知道什麼基因是重要的,我們可以給他們一種不同的藥物!

我承認,前綴樹和基因組學之間的聯繫不太緊密。其實前綴樹的最直接用法就是用來查字典啦!但只講字典有點太無聊了。

前綴樹的原理

想像一下,你有一棵樹,每個節點都有一個包含 26 個子節點的數組,每個子節點對應一個英文字母。(如果要包含其他字元,可以將 26 更改為不同的值。)要在你的樹中表示單詞,你將從根節點開始,沿著路徑向下走,並在每個節點添加一個字母。

例如於「tea」這個詞,你從根開始,被引導到 t 節點,然後是 e,最後是 a。因此,搜尋單字需要 O(N)的時間(其中 N 是單字的長度),如果單字的首碼不存在,則可以提前結束。如果我查詢「zzzzzzzz」,樹可以在「zz」之後結束查詢。

環形緩衝區(ring buffer)

環形緩衝區是使用普通數組的一種非常好的方式,它主要被用於處理數據流。

誰會使用環形緩衝區?

說不定 Netflix 會用?

我用 Google 搜尋「Netflix ring buffer」,發現了他們發佈了一些開源環緩衝區代碼。但問題是,公司真的會用他們已經開源的代碼嗎?

環形緩衝區的原理

好啦好啦。真的還有人在讀這篇文章嘛。

如果你讀到了這兒,說明你基礎一定還不錯,那就直接去維基百科看一下這個資料結構吧,比前兩個簡單多了!

總結一下,今天文摘菌介紹了三個重要的資料結構:布隆過濾器(bloom filter),前綴樹(prefix trie),環形緩衝區(ring buffer)。

想當一個聰明工程師,這些結構知識值得你熟記!

原文 傳送門

(本文經 大數據文摘 授權轉載,並同意 TechOrange 編寫導讀與修訂標題,原文標題為 〈想伪装成资深程序员?知道这三个数据结构就够了 〉 。首圖來源:Wikipedia Commons

更多工程師技能大補帖

程式、演算法差在哪?比起學程式,你更應該了解演算法

程式自學十年心得:想吃這行飯,學好演算法與資料結構才能讓你站穩腳步

機器學習成效開到最大!介紹 4 個超好用的 Shell 程式技巧


全方位掌握消費者數位軌跡

AI 如何有效提升電商業績、降低導入成本?

《領取白皮書》

點關鍵字看更多相關文章: