這份演算法攻略,我拿到了5個大廠的offer
每個時代,都不會虧待會學習的人。
大家好,我是 yes。
我持續在 LeetCode 刷演算法題將近有一年半的時間了,這一年半以來我對演算法的看法改變了很多,但是實話實說支援我前進的還是面試。
在之前的文章提到過我是面試驅動型選手,我享受面試官問我啥我都嘴角一翹微微一笑的那種不羈,而近年來演算法在面試中的比重越來越大,所以我花了很大的精力去攻克演算法這道難關,確實有點難。
我不是天賦型選手,甚至覺得自己有點蠢,在刷題的過程中經常被各種打擊,最誇張的就是同一道題刷了 4 次,過一段時間去寫還是不會,從下面的這些草稿可以看出我當時內心的那種崩潰。
當然還有給自己加油打氣的(不要嫌棄我的字丑哈)。
經過了三本書的系統學習、一年半的刷題,三篇專欄的多次學習,搞了很多大廠的真題練習,基本上有點穩了。
這篇文章想分享一下我面向面試學習演算法的一些心得,所以演算法大牛、演算法愛好者可以關閉這個頁面了,這是一篇面向一般程式設計師的演算法面試攻略。
在去年我還參加一個話題回答,「數據結構與演算法的學習中,面對經典程式碼是選擇自己實現還是背誦?」,一不小心就被選上中獎了,嘿嘿。本來還想把獎品搞個抽獎送出去的,但是這個包裝被我扔了,因為兩張演算法大地圖需要長筒來裝,不好運輸,之後再看看吧。
來看看我是怎麼回答這個問題的吧。
數據結構與演算法的學習中,面對經典程式碼是選擇自己實現還是背誦?
我覺得學習演算法就是理解+持續練習+刻意的背誦(有選擇性的背誦)。
有些人學習演算法可能是興趣愛好啥的,很直白的說我就是功利性的學習,並且能夠因為功利心而持續學習。
因為功利我想快速得到收益的最大化,但是欲速則不達,因此我會在功利的情況下理性的學習演算法。
1、首先鞏固基礎,萬丈高樓平地起。演算法就是使用各種數據結構按照一定的流程運行,管你五花八門稀奇古怪的演算法題都逃脫不了數組和鏈表。在數組和鏈表之上特殊功能化了很多有特殊意義的數據結構:隊列,棧等。
數據結構都是因為不同的場景有不同的需求而演化而來,因此在某個場景數組更合適,某個場景鏈表更合適,你所需要知道的就是它們分別的優缺點和使用的場景,並能知其然而知其所以然。
例如數組下標訪問高效,是因為記憶體連續,因此對 CPU 快取親和性更高等。這樣使用才能遊刃有餘,有的放矢。
2、持續練習,光說不練假把式,單單看是沒用的,不上手便成空。
我沒那演算法的天賦,在我認為我對基本數據結構有了一定的了解的情況下,看到有些演算法題還是蒙圈,沒那思路,腦袋空空,那也只能練唄。
遇到完全沒思路的題目最多 5 分鐘我就會去找題解,有可能 2 分鐘,因為功利嘛,還有一部分我覺得我沒那腦子我認清自己哈哈哈。
但是在找題解的時候我是秉著一個必須充分理解的目的去的,不理解不放棄,開玩笑答案至少我還是得看懂吧(這句話我現在收回,當時還是太年輕)。
當然這裡的不放棄不是指這半天或者一天內一定要搞定。有時候就會陷入瓶頸,隔一天,或者去玩一下回來就會豁然開朗。
通過持續的練習,你腦子裡就會漸漸的了解這些題目的套路,你也能更好的關聯各種數據結構,這就是感覺來了,你會發現自己變聰明了,這就是要進入良性循環了,並且持續的練習,你會發現某一天如果你沒寫演算法題的時候會有一種罪惡感!
還有我不會藉助 IDE 寫,就在 LeetCode 上直接寫,一個一個自己敲,時刻為著以後面試寫題作準備,沒錯就是這麼功利。
3、刻意的背誦(有選擇性的背誦)
有人會說演算法是要理解的,死記硬背是沒用的。沒錯理解是肯定要理解的,死記硬背肯定過兩天就會忘了。
但是我認為單單理解還是不夠的,理解+練習是可以讓你做出題目,但是做不到讓你不假思索的做出題目,在面試的這種緊張的情況下,只有類似肌肉記憶才能給面試官最強烈的打擊,稍微的緊張可能就會導致連環出錯,滿盤皆輸!
因此對於那些經典的程式碼,常用的例如二分查找,快排等我都會刻意的背誦,達到聽到二分查找,腦子裡就有那麼些程式碼出現的程度,沒錯我還是這麼的功利。
也就是說平時刷的演算法題都要理解,但是一些經典的程式碼我認為理解還不夠,需要背誦形成肌肉記憶。
有些人可能會覺得,沒啥好背的啊,多多練習就會了,額其實多多練習就等於背,是吧你說你寫個十幾遍不就等於背么。只是我是刻意的背。
嘖嘖,我覺得我說的真好,哈哈哈。
再補充一下這個回答的個別觀點:
1、掌握好基礎,也就是那些常用的數據結構和演算法,比如隊列、棧、堆、歸排、快排、二分、動態規劃等等,熟悉這些經典數據結構和演算法,通透的得知他們的適用場景。
解題無非就是將它們套上去,絕對不會叫你創新,你所做的就是套模板,就看你模板選的對不對,套的熟不熟罷了。
2、持續練習,這玩意是最重要的。因為叫很多人看東西沒問題,讓他上手就會有拖延症,感覺有點麻煩。
但是演算法就是得練,沒有什麼其他選擇,不用耍啥小聰明,除非你過目不忘。
因為它的解題思路不太符合正常人的思考,所以你需要持續的練習,讓你的思維轉變過來,形成看到這類的題目就會有應激反應。
還有兩點很關鍵,我強調一下:
- 不要花太多時間在一道題上,幾分鐘沒思路就看題解,看了題解再進行理解和默寫。
- 不要用 IDE 寫,面試的時候就是沒聯想提示的,有時候甚至是手寫,所以在平時就要做好準備,不打無準備之仗。
上面其實講的就是平日學習和刷題的套路,接下來講講如何上手。
上手攻略
我選擇小爭哥的《數據結構與演算法之美》專欄,這個專欄我刷了兩遍,雖說我還看了別的專欄,但是這個夠了,上手絕佳,貼個專欄的圖吧。幾乎涵蓋了所有的數據結構和演算法書籍涉及到的知識點。
我就是看這個入門的,基本的套路講解的很全,推薦先把專欄全面的看一遍,把每節課涉及的到程式碼自己敲一遍。
可以按以下學習順序、難易程度和重點程度來學習這個專欄。
然後再二刷,二刷的目的是提煉和總結,我來貼一下我之前的個別章節總結,這是之前參加演算法打卡活動留下的。
刷完之後,一些經典數據結構和演算法至少都認識,也說得上來,基本上算是入門了。
然後再去看《演算法(第4版)》這本書,雖說我看了三本演算法書但是我覺得這本夠了。
一般而言大家都會先推薦書,畢竟書都比較全也更加系統,但是我喜歡反其道而行之。
因為書太厚了,厚就容易勸退,特別是在你對一個領域不太熟悉的時候。
所以我更喜歡先去學別人提煉過的付費專欄,提煉出來的都是重點,讓我對核心知識脈絡有了充分的認識之後,再去看書來查漏補缺,建立完善的體系。
因為在你已經了解大致核心知識點後,你再去看大頭書就會有一種熟悉感和共鳴感,這種感覺可以讓你把書從頭看到尾。
至於為什麼看了專欄之後還得看書,是因為專欄畢竟是被人提煉過的,而書的知識點大多都是完整的,你先吸收別人提煉過的知識點,帶著別人的想法再去系統的學習,從其中再糅合出自己的總結,這樣東西才真的是你的。
系統的學習完這本書之後,感覺自己好像很厲害了?
並不是。
你還需要去實戰,碰一碰真正的面試題,紙上學來終覺淺。
當然我是在一開始就刷題了,並不是等專欄、書都看完了才上手,我建議在刷專欄期間就去刷題練練手。
我是在 2016 年才知道 LeetCode 這個網站的,當時我看到同項目組的研究生在刷,他在國外讀研,他說這玩意是必須刷的。
那時候還沒中文版,全英文的我看著很高級就上去玩一玩,不怕各位笑話,第一題就不會,只能寫出暴力解法,循環兩個數相加之和來對比。
看了題解之後恍然大悟,暗罵自己好蠢,然後繼續往後刷了幾題成功被勸退,然後就沒有然後了…
到現在 LeetCode 上的題也越來越多了,按順序刷就太”蠢”了,根本就沒必要全刷,要刷經典題,歸類刷,把一類題型刷出感覺來才罷休。
一般經典的常見的類型無非是 BFS、DFS、雙指針、前綴、背包、二分、鏈表、二叉樹、滑動窗口、堆(Top K)、棧、動態規劃、回溯、滑動窗口、位運算、圖、各種排序等等。
其實還有一些數學類型的題目,我選擇放棄,哈哈哈。
正常情況下面試也不會問數學類型的,至於上述所說的題型,已經有一份很 nice 的演算法筆記幫你總結了,很完備,很貼心,1730 頁,20W 字,匯總了各大題型,基本上每題都附上了各大佬們的高品質解題思路,並附上鏈接,方便查看原文,我隨便截幾張圖給大家看看。
這個演算法匯總是我向魴姐討來的,一位刷題找工作的研三黨,魴姐之後打算提供一些關於學習,簡歷修改,求職路線的1v1輔導服務,敬請期待~
這份總結 PDF 請拉到文末獲取。
解題技巧
我再來提一個我個人認為很重要的解題技巧:主幹先行再填充細節。這個編碼技巧其實不僅僅關乎演算法,平日的程式碼也建議按這個思路寫。
我舉冒泡排序這個很簡單的例子來解釋一下這句話的意思。
箭頭指向的其實就是交換兩個位置內容的程式碼,可以封裝一下,變成下面這樣。
這個例子的程式碼太簡單了所以不封裝也沒事,不過我想提的就是這種封裝的思想。
一般而言面試官可以在線實時看到你的編碼,他看的不僅僅是你的題解,還包括你的程式碼風格,排版等等,這也是很關鍵的一部分。
所以碰到是一些程式碼比較多的題目時候,注意方法的封裝,不要一大坨都寫在一起。
主幹先行的意思是,例如上面的 swap 方法的實現先不要寫,你當自己已經實現了 swap 方法來用就行,這就是先完善主幹,清晰思路。 這樣的程式碼看起來就不會凌亂,你自己調理也比較清晰。
等主幹寫完了之後,再去實現你封裝的方法,也就是填充細節。
當然有人是一坨寫完了,然後再進行重構,但是我覺得重構是重構,和我說的這種編碼技巧不是一個方向。
我要表達的點是在編寫程式碼的時候展示清晰的思路,並且對你個人而言這種做法也更簡單,不會讓一些細節干擾你的主線。
可能就冒泡排序而言太簡單的,感受不太深刻,大家可以在平時刷題時候練練,相信你能體會到這種做法的好處。
最後
可能大家也看過很多學習演算法的分享,很多本書、很多網站、很多課程,多並不一定是好事。
我個人認為一個專欄、一個網站、一本書、一份演算法筆記對於我這種後端程式設計師來說足以,不要想著這個課好像不錯,這個書好像很多人推,我可以很負責的告訴你,就我提到的這幾個你吃透了,你基本上是「化神期」修士了。
還有上面的提到的魴姐的演算法筆記,後台回復「123」即可領取。
我是 yes,從一點點到億點點,我們下篇見。