天天看點

算法學習指南

之前發的那篇關于架構性思維的文章,我也發到了不少其他圈子,受到了大家的普遍好評,這一點我真的沒想到,首先感謝大家的認可,我會更加努力,寫出通俗易懂的算法文章。

有很多朋友問我資料結構和算法到底該怎麼學,尤其是很多朋友說自己是「小白」,感覺這些東西好難啊,就算看了之前的「架構思維」,也感覺自己刷題乏力,希望我能聊聊我從一個非科班小白一路是怎麼學過來的。

首先要給懷有這樣疑問的朋友鼓掌,因為你現在已經「知道自己不知道」,而且開始嘗試學習、刷題、尋求幫助,能做到這一點本身就是及其困難的。

關于「架構性思維」,對于一個小白來說,可能暫時無法完全了解(如果你能了解,說明你水準已經不錯啦,不是小白啦)。就像軟體工程,對于我這種沒帶過項目的人來說,感覺其内容枯燥乏味,全是廢話,但是對于一個帶過團隊的人,他就會覺得軟體工程裡的每一句話都是精華。暫時不太了解沒關系,留個印象,功夫到了很快就明白了。

下面寫一寫我一路過來的一些經驗。如果你已經看過很多「如何高效刷題」「如何學習算法」的文章,卻還是沒有開始行動并堅持下去,本文的第五點就是寫給你的。

我覺得之是以有時候認為自己是「小白」,是由于知識某些方面的空白造成的。具體到資料結構的學習,無非就是兩個問題搞得不太清楚:這是啥?有啥用?

舉個例子,比如說你看到了「棧」這個名詞,老師可能會講這些關鍵詞:先進後出、函數堆棧等等。但是,對于初學者,這些描述屬于文學詞彙,沒有實際價值,沒有解決最基本的兩個問題。如何回答這兩個基本問題呢?回答「這是啥」需要看教科書,回答「有啥用」需要刷算法題。

PS:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部釋出在 labuladong的算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種算法套路後投再入題海就如魚得水了。

一、這是啥?

這個問題最容易解決,就像一層窗戶紙,你隻要随便找本書看兩天,自己動手實作一個「隊列」「棧」之類的資料結構,就能捅破這層窗戶紙。

這時候你就能了解「架構思維」文章中的前半部分了:資料結構無非就是數組、連結清單為骨架的一些特定操作而已;每個資料結構實作的功能無非增删查改罷了。

比如說「列隊」這個資料結構,無非就是基于數組或者連結清單,實作 enqueue 和 dequeue 兩個方法。這兩個方法就是增和删呀,連查和改的方法都不需要。

二、有啥用?

解決這個問題,就涉及算法的設計了,是個持久戰,需要經常進行抽象思考,刷算法題,培養「計算機思維」。

之前的文章講了,算法就是對資料結構準确而巧妙的運用。常用算法問題也就那幾大類,算法題無非就是不斷變換場景,給那幾個算法架構套上不同的皮。刷題,就是在鍛煉你的眼力,看你能不能看穿問題表象揪出相應的解法架構。

比如說,讓你求解一個迷宮,你要把這個問題層層抽象:迷宮 -> 圖的周遊 -> N 叉樹的周遊 -> 二叉樹的周遊。然後讓架構指導你寫具體的解法。

抽象問題,直擊本質,是刷題中你需要刻意培養的能力。

三、如何看書

直接推薦一本公認的好書,《算法第 4 版》,我一般簡寫成《算法4》。不要蜻蜓點水,這本書你能選擇性的看上 50%,基本上就達到平均水準了。别怕這本書厚,因為起碼有三分之一不用看,下面講講怎麼看這本書。

看書仍然遵循遞歸的思想:自頂向下,逐漸求精。

這本書知識結構合理,講解也清楚,是以可以按順序學習。書中正文的算法代碼一定要親自敲一遍,因為這些真的是紮實的基礎,要認真了解。不要以為自己看一遍就看懂了,不動手的話了解不了的。但是,開頭部分的基礎可以酌情跳過;書中的數學證明,如不影響對算法本身的了解,完全可以跳過;章節最後的練習題,也可以全部跳過。這樣一來,這本書就薄了很多。

相信讀者現在已經認可了「架構性思維」的重要性,這種看書方式也是一種架構性政策,抓大放小,着重了解整體的知識架構,而忽略證明、練習題這種細節問題,即保持自己對新知識的好奇心,避免陷入無限的細節被勸退。

當然,《算法4》到後面的内容也比較難了,比如那幾個著名的串算法,以及正規表達式算法。這些屬于「經典算法」,看個人接受能力吧,單說刷 LeetCode 的話,基本用不上,量力而行即可。

四、如何刷題

首先聲明一下,算法和數學水準沒關系,和程式設計語言也沒關系,你愛用什麼語言用什麼。算法,主要是培養一種新的思維方式。所謂「計算機思維」,就跟你考駕照一樣,你以前騎自行車,有一套自行車的規則和技巧,現在你開汽車,就需要适應并練習開汽車的規則和技巧。

LeetCode 上的算法題和前面說的「經典算法」不一樣,我們權且稱為「解悶算法」吧,因為很多題目都比較有趣,有種在做奧數題或者腦筋急轉彎的感覺。比如說,讓你用隊列實作一個棧,或者用棧實作一個隊列,以及不用加号做加法,開腦洞吧?

當然,這些問題雖然看起來無厘頭,實際生活中也用不到,但是想解決這些問題依然要靠資料結構以及對基礎知識的了解,也許這就是很多公司面試都喜歡出這種「智力題」的原因。下面說幾點技巧吧。

盡量刷英文版的 LeetCode,中文版的“力扣”是閹割版,不僅很多題目沒有答案,而且連個讨論區都沒有。英文版的是真的很良心了,很多問題都有官方解答,詳細易懂。而且讨論區(Discuss)也沉澱了大量優質内容,甚至好過官方解答。真正能打開你思路的,很可能是讨論區各路大神的思路荟萃。

PS:如果有的英文題目實在看不懂,有個小技巧,你在題目頁面的 url 裡加一個 -cn,即 https://leetcode.com/xxx 改成 https://leetcode-cn.com/xxx,這樣就能切換到相應的中文版頁面檢視。

對于初學者,強烈建議從 Explore 菜單裡最下面的 Learn 開始刷,這個專題就是專門教你學習資料結構和基本算法的,教學篇和相應的練習題結合,不要太良心。

最近 Learn 專題裡新增了一些内容,我們挑資料結構相關的内容刷就行了,像 Ruby,Machine Learning 就沒必要刷了。刷完 Learn 專題的基礎内容,基本就有能力去 Explore 菜單的 Interview 專題刷面試題,或者去 Problem 菜單,在真正的題海裡遨遊了。

無論刷 Explore 還是 Problems 菜單,最好一個分類一個分類的刷,不要蜻蜓點水。比如說這幾天就刷連結清單,刷完連結清單再去連刷幾天二叉樹。這樣做是為了幫助你提取「架構」。一旦總結出針對一類問題的架構,解決同類問題可謂是手到擒來。

五、道理我都懂,還是不能堅持下去

這其實無關算法了,還是老生常談的執行力的問題。不說什麼破雞湯了,我覺得解決辦法就是「激起欲望」,注意我說的是欲望,而不是常說的興趣,拿我自己說說吧。

半年前我開始刷題,目的和大部分人都一樣的,就是為畢業找工作做準備。隻不過,大部分人是等到臨近畢業了才開始刷,而我離畢業還有一陣子。這不是炫耀我多有覺悟,而是我承認自己的極度平凡。

首先,我真的想找到一份不錯的工作(誰都想吧?),我想要高薪呀!否則我在朋友面前,女神面前放下的騷話,最終都會反過來啪啪地打我的臉。我也是要恰飯,要面子,要虛榮心的嘛。賺錢,虛榮心,足以激起我的欲望了。

但是,我不擅長 deadline 突擊,我了解東西真的慢,是以幹脆笨鳥先飛了。智商不夠,拿時間來補,我沒能力兩個月突擊,幹脆拉長戰線,打他個兩年遊擊戰,我還不信耗不死算法這個強敵。事實證明,你如果認真學習一個月,就能夠取得肉眼可見的進步了。

繼續閱讀