如何學(xué)習(xí)算法的相關(guān)文章,大家估計也見過不少,每個人的學(xué)習(xí)方法都不盡相同,這很正常,并且,對于不同的選手來說,例如打 ACM 的玩家不打比賽的玩家來說,訓(xùn)練的方式也有不少差異,所以別人所說的學(xué)習(xí)方式,更多的是作為你的一種參考。
在我的四年大學(xué)里,花在學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)/算法的時間可以說是最多的了,不過我并不后悔,因為算法基礎(chǔ)的沉淀,給我后面的成長帶來了很多幫助,所以今天這篇文章,帥地會根據(jù)自己的理解,談一談如何學(xué)習(xí)算法,如果你是這方面的小白的話,還是可以參考一下。
不過,在寫之前,我想先回答幾個問題,或許對于那些剛?cè)腴T的同學(xué),有些許幫助。
一、簡單回答幾個問題
1、有必要學(xué)算法嗎?
很多過來人可能都會跟你說,算法沒必要學(xué),你又不是算法崗,工作其實(shí)就天天 crud,用啥都是封裝好的,學(xué)了也用不到,慢慢也就忘了。
這篇文章不是來跟你辯論有沒有必要學(xué)算法的,我就做個簡單的回答,我的答案是,有必要學(xué)一學(xué),一個現(xiàn)實(shí)且勢利的原因,估計就是 ----- 大廠都喜歡考察算法了,不信你去問問剛剛參加過 2020 校招的同學(xué),我自己也參加過 2019 的秋招,算法考察,基本無處不在,如果想要獲得面試機(jī)會,那么就得筆試,而筆試,大部分公司都是編程題,即算法題,而且,面試中也會經(jīng)常問到算法,數(shù)據(jù)結(jié)構(gòu)。顯然,從找公司的角度看,不學(xué)算法你會失去很多面試的機(jī)會。然而,更重要的還是,程序 = 數(shù)據(jù)結(jié)構(gòu) + 算法,算法基本功打好,可以讓我們走的更遠(yuǎn)。
2、學(xué)算法好慢/好難,是我不夠聰明不適合學(xué)算法嗎?
答不是的,如果只是學(xué)習(xí)下常見算法,以后應(yīng)付下面試/筆試 + 分析下工作遇到的一些問題,那么我覺得,還論不到天賦來做審判,這絕對不是雞湯,當(dāng)然,如果你想打 ACM,拿各種獎的,那我就不大清楚了。
簡單的說,學(xué)算法好慢/好難主要還是你代碼寫的太少了,做的題太少了,雖然有些人學(xué)起來會慢一些,特別是入門那會,但一旦過了這道坎,學(xué)起來就會快很多,所以,不要還沒學(xué)之前,或者學(xué)了一時半會覺得自己沒有 get 到點(diǎn),就否定自己。
二、入門數(shù)據(jù)結(jié)構(gòu)與算法
我是學(xué)習(xí)了《數(shù)據(jù)結(jié)構(gòu)與算法分析》這本書之后,再去學(xué)習(xí)各種算法思想 + 刷題的,所以我覺得,入門算法的第一步,是在你學(xué)會了一門語言之后(帥地當(dāng)時學(xué)的是 C 語言),靜下心來啃一本數(shù)據(jù)結(jié)構(gòu)與算法的書籍,例如我說的《數(shù)據(jù)結(jié)構(gòu)與算法分析:xx語言描述版》,也可以是《大話數(shù)據(jù)結(jié)構(gòu)》等等。
怎么學(xué)這本書呢?
我覺得,對于剛剛?cè)腴T的選手來說,沒啥技巧,也不要迷戀于各種快捷的方法,咱們老實(shí)點(diǎn),當(dāng)個普通人,就跟著書學(xué),按照順序?qū)W就可以了,然后把里面例子的代碼,都至少打一遍,當(dāng)然,還需要跑通,結(jié)果要符合預(yù)期,如果不符合,就調(diào)試到符合預(yù)期。
注意,上面那句話我打了顏色,說明這句話非常重要,千萬不要覺得自己理解了,就不寫代碼了,例如覺得自己理解了鏈表的增刪改,然后就不寫代碼了,在編程這一塊,感覺自己理解,和成功實(shí)現(xiàn)且符合預(yù)期,特么就是兩回事。
之后一般每一章都會有習(xí)題,不需要全部做,自己挑幾道做就好了,就算是一眼就秒殺知道怎么做的,其實(shí)也可以實(shí)現(xiàn)一遍,如果不懂,可以找答案,但是一定要自己在電腦上把代碼敲打出來,然后跑通。當(dāng)你把書上 90% 的代碼例子跑通,那么,這本書有一半的知識,就是你的了。
這里我說下,你們找的書籍,最好是有完整代碼實(shí)現(xiàn)的,因為有些書籍,為了具有通用性或者嚴(yán)謹(jǐn)性,是采用偽代碼來實(shí)現(xiàn)的,我不建議初學(xué)者用這類書籍,因為容易一臉蒙蔽,代碼也不好跑通驗證,所以如果你覺得自己是普通人,那么就找一本有完整代碼的書籍來看吧,然后乖乖把代碼的代碼敲打跑通起來。
不要眼高手低,當(dāng)你積累到一定的代碼數(shù)量,你就會慢慢來感覺了。
當(dāng)你學(xué)完了鏈表、隊列、棧、二叉樹、哈希表等最基本的數(shù)據(jù)結(jié)構(gòu),其實(shí)你就算入門了,這個時候其實(shí)你已經(jīng)具備了去 leetcode 刷題的能力了。不過在學(xué)習(xí)過程中,特別是到了圖那部分,會涉及到很多算法,例如最短路徑,深度搜索和廣度搜索…當(dāng)然,還有二叉樹的各種遍歷等。
如果你對遞歸一點(diǎn)也不懂,那么你會被虐的,腦袋也容易被爆棧,因為,遞歸真的無處不在,這也引出了我覺得入門算法非常重要的一個算法思想 --- 遞歸算法。
三、刷題之前的一些準(zhǔn)備
如果你連最基本的數(shù)據(jù)結(jié)構(gòu),例如鏈表,隊列,棧,二叉樹都沒有接觸過,那么我是不建議你去 leetcode 刷題的,所以我上面先說了先入門一下數(shù)據(jù)結(jié)構(gòu)與算法,當(dāng)你學(xué)習(xí)了這些基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)之后,其實(shí)已經(jīng)具備了刷題的能力了。
不過,我還是希望你能在學(xué)習(xí)一些算法思想,一般就這幾種
1、遞歸
2、枚舉
3、貪心
4、回溯
5、動態(tài)規(guī)劃
但是,其中最重要的,我覺得就是遞歸,其他的幾種算法,也都會有遞歸的影子,并且我剛才說圖相關(guān)算法、二叉樹的遍歷等,也都包含遞歸的使用。
所以,在你刷題之前,或者在學(xué)習(xí)二叉樹、圖相關(guān)算法遇到遞歸的時候,我希望你能靜下心來,去學(xué)一學(xué)遞歸,我也會告訴你,對于初學(xué)者,遞歸很難,我是被無數(shù)次折騰,無數(shù)次看答案似懂非懂之后,才突然醒悟了。
你不需要把它學(xué)的很精通,但是你要懂一些基本的遞歸題,知道遞歸是怎么一回事,例如最簡單的斐波那契數(shù)列得會用遞歸做吧?階乘也得會吧(雖然不是最優(yōu)解)。
所以,死磕入門數(shù)據(jù)結(jié)構(gòu),可以學(xué)習(xí)下一些算法思想,而遞歸,你必須得入門,至于動態(tài)規(guī)劃、回溯,我覺得慢點(diǎn)學(xué)也沒有,可以后面刷題遇到時在學(xué),而枚舉、貪心,相對比較簡單。
關(guān)于遞歸的,可以看我之前的一遍入門級的文章:為什么你學(xué)不會遞歸?告別遞歸,談?wù)勎业囊恍┙?jīng)驗
評價還是很好,之后找些簡單的題做,例如在 LintCode 那些 easy 的題(leetcode 和 lintcode 類似,類似于一個中文版,一個英文版)
四、如何刷題
終于,到了刷題這一部分了,如果要說學(xué)算法的捷徑,那么刷題便是最好的捷徑,如果你刷的題很少,達(dá)不到一定的量,那么再多的捷徑,估計也沒啥用,只有在滿足一定題量的情況下,才適合來談?wù)撍^的技巧。
1、先說一說筆試
不過在刷題之前我想先說一說筆試,如果筆試不考算法,面試也不考算法,那么我可能在學(xué)習(xí)算法的這條路上,會少了很多的積極性,你可能會覺得我很功利,但是我覺得,帶著功利性的目的去學(xué)習(xí)算法,也是完全沒問題的。
在校招的筆試中,其實(shí)這些筆試題還是挺難的,你在 leectode 可以做出 hard 級別的題,但在筆試中,可能連 medium 級別的都做不出,因為筆試的題,都比較靈活,基本都會通過實(shí)際的例子來引出一道題,你可能不知道要使用哪種方法來做比較好,有些還是多種方法的結(jié)合。
對于筆試的題型,我之前也總結(jié)過,無非是以下幾種
(1)、基本數(shù)據(jù)結(jié)構(gòu)的考察:這類題我覺得是比較簡單的,主要考場基本數(shù)據(jù)結(jié)構(gòu)的操作,例如二叉樹的層序遍歷,鏈表的逆序等,當(dāng)然,它不會直接告訴你,讓你來逆序或者遍歷。
(2)、某種算法思想的掌握:這類題你掌握了某種算法思想,就會比較容易,如果不懂,那就涼涼了。例如動態(tài)規(guī)劃、回溯、枚舉、深度/廣度、貪心、二分等。其中,我覺得動態(tài)規(guī)劃考的挺多,還要就是 回溯+深度/廣度。
(3)、邊界條件的考察:這類型的題,估計你一看就有思路,知道該怎么做,但是,它的邊界條件特別多,需要分很多種情況來討論,特別容易出錯,有時候會讓人陷進(jìn)去,越做越復(fù)雜,這類題主要考場你的思維嚴(yán)謹(jǐn)程度。
(4)、找規(guī)律、數(shù)學(xué)公式:這類型的題,主要是根據(jù)數(shù)據(jù)之間的一些關(guān)系,來找一些規(guī)律,進(jìn)而推出他們的通用公式,就像我們高中時,找數(shù)列的同項一樣。
2、按分類刷題
上面我列了筆試的題型,并且跟你說了筆試是真的挺難的,那么對于我個算法小白來說,該如何做好呢?
我的建議是,分類刷題,階段性總結(jié)。例如最開始可以在 LintCode 按照鏈表/二叉樹/遞歸等這些標(biāo)簽來刷,因為這樣可以讓你深入掌握每一種方法。
當(dāng)然,筆試的題之所以難,是因為我們往往不知道用哪一種方法做好,或者說具體屬于哪一種題型,那么還有必要分類刷題嗎?
答是有必要的,只有當(dāng)你熟悉每一種題型,你才能靈活使用他們,進(jìn)而解決各類復(fù)雜的題,這就如同你在練功夫的時候,前期你需要把每個招式都打扎實(shí)了,之后才能靈活把各個招式連接起來,融合貫通。刷題也是一樣,前期先分類,把每個題型掌握起來,后期咱們再隨機(jī)練習(xí),慢慢著就能靈活應(yīng)用了。
不過,每次刷了一部分題型之后,我覺得還有必要做一些總結(jié),或者說總結(jié)一些刷題模版,例如對于二分法查找,其實(shí)好幾種題型總結(jié)起來,就是開閉區(qū)間的組合,你可以把他們總結(jié)起來,例如什么時候用開區(qū)間,什么時候用閉區(qū)間。
有人可能會說,模版是死的,真的有必要總結(jié)嗎?
我覺得有必要總結(jié),但沒必要死記,總結(jié),只是加深你的理解,當(dāng)然,如果你在做題的時候,剛好記住了自己的模版,可以直接套上去,那肯定更好。但是,就算忘了也沒事,通過自己的總結(jié),你其實(shí)是知道怎么做的了,只是還需要你多花一點(diǎn)時間,快速模擬討論下各種情況,一樣能夠做出來的。
也就是說,最開始刷題的時候,可以分類刷題,并且階段性總結(jié),如果你是初學(xué)者,可以先從簡單的題做起,例如我剛才說的,簡單的遞歸題,之后一些二叉樹、鏈表的題,因為你可能剛剛學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)不久,剛好可以加深你的理解。
五、刷題時的一些注意點(diǎn)
當(dāng)我們在做一道題的時候,可能會遇到兩種情況,一種是這道題,特么秒殺,一眼就懂思路;一種是,一臉蒙蔽,太難了吧。
一眼就懂思路,有必要做嗎?
我的答案是,有必要做。千萬不要眼高手低,看著簡單,做起來不一定簡單,AC 之后,你還要去討論區(qū)看看大佬們是怎么做的,因為有些人的代碼,真的寫的很簡潔,看著就很舒服,咱們可以多學(xué)一學(xué)的,當(dāng)然,也有可能那個人就是你自己。
代碼寫多了,有時候,你就會發(fā)現(xiàn)自己真的變強(qiáng)了,寫起代碼來,bug 也越來越少了,分分鐘 AC 一道題。
盡量最優(yōu)解
其實(shí)對于很多題,如果不看時間復(fù)雜度和空間復(fù)雜度,單單只是 AC,那還是很容易的,但是一提交,你的代碼可能只打敗了百分之幾的人,顯然我們是不能滿足于這種代碼的。
當(dāng)你做一道題時,一開始可以先暴力做,但后面,還得想想該如何優(yōu)化,想不出也沒事,可以討論區(qū)找空間/時間復(fù)雜度更低的代碼,或者直接搜索引擎搜索,一般都能搜到別人的代碼。
之后跟著別人的代碼,自己再實(shí)現(xiàn)一波,盡可能把最優(yōu)解的代碼實(shí)現(xiàn)起來。千萬不要為了 AC 而 AC,不是 AC 的越多就越強(qiáng)的,當(dāng)你入門之后,更多的是要總結(jié)方法,尋找高效率的代碼。
六、總結(jié)
說到算法的學(xué)習(xí)方式,對我來說,真的沒有什么捷徑之類的,就是像我上面說的,先找本書死磕入門數(shù)據(jù)結(jié)構(gòu),就跟著書的例子,把例子跑起來就好了,跑起來也不是一件簡單的事情。之后就去接觸下一些算法思想,后面就可以分類刷題了,刷題就是最好的捷徑了。
當(dāng)然,不要 AC 之后就完事了,應(yīng)該盡可能尋找最優(yōu)解,當(dāng)你積累了一定的題量,那么你真的會發(fā)現(xiàn)自己變強(qiáng)了,突然感覺遞歸也就那么一回事。
我學(xué)習(xí)算法時,基本看書 + 網(wǎng)上刷題,也很少看視頻,因為我覺得看視頻比較花時間,不過我之前在班里還是看到部分人喜歡看視頻的,至于看書好還是看視頻好,這個看個人喜好吧,也沒有說哪種就一定更好。
責(zé)任編輯:xj
原文標(biāo)題:談一談「如何學(xué)好算法」
文章出處:【微信公眾號:算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
算法
+關(guān)注
關(guān)注
23文章
4624瀏覽量
93119 -
編程
+關(guān)注
關(guān)注
88文章
3634瀏覽量
93859
原文標(biāo)題:談一談「如何學(xué)好算法」
文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論