學算法要讀《算法導論》嗎?

這篇文章是我學習算法的心得,希望它能夠給一些將要學習算法且準備要讀大部頭算法書籍的朋友一些參考,節省一些時間,也爲了給經典的“黑皮書”祛魅,我覺得這些書籍在大部分互聯網從業者心中已經不再是進步的階梯,而是恐懼的陰影了,因爲當一些學習路線中列出這些書目時,評論區多是調侃少是交流和討論。在這之前我也這些書抱有讀起來很困難的看法,但是在我參考過《算法導論》之後,我覺得它更像是一杯“雞尾酒”:正文學習起來相對容易,能幫大家建立基礎,後續的習題和實驗,能幫助有需要的人進行深入學習,擴展的高級數據結構和數論等章節也能進行探索,就看大家怎麼來利用了。

開始學習算法的契機是23年初參加《Hello 算法》開源項目的內容貢獻,發現自己算法基礎知識匱乏,索性準備系統地學習一下算法相關的知識,在這前後一共讀了4本書:《Hello 算法》、《數據結構與算法之美》、《算法(第四版)》和《算法導論》(參考了前16章),學習期間在朋友的建議下實踐了艾賓浩斯學習法,覺得收貨良多。所以,本文會分兩部分,分別介紹算法的學習指南和學習方法,希望對大家能有啓發:

算法學習指南

我採用的專題閱讀學習,以《算法》爲主要參考書目,逐章閱讀,每學習完一個章節都會再去閱讀其他書籍的對應章節作爲內容補充,並結合章後的習題練習(我覺得沒有練習的算法學習都是空架子,因爲大多時候看會了很可能還是寫不出來,但是官方給出的參考答案補全,可以參考《算法(第四版)》參考答案開源項目)。但是事實上並不是這些書中所有的內容都值得參考,所以可以參照下面的學習方法:

《算法》的第二章排序介紹了時間複雜度爲O(n^2)和O(logn)的排序算法,它並沒有直接介紹時間複雜度爲O(n)的桶排序、計數排序和基數排序,而是將它們放在了第五章的字符串排序中,我認爲這部分並不好,所以在完成這一章的學習後,需要參考《Hello 算法》的第十一章或者《算法導論》的第八章,我認爲參考前者更合適一些。

《算法》的第三章在介紹紅黑樹時,它寫的是左傾紅黑樹(與2-3查找樹同構),該數據結構是這本書的作者先前發表的一篇論文,它是經典紅黑樹的變體,實現相對容易。不過,在Java語言中TreeMap的實現採用的經典紅黑樹(與2-3-4查找樹同構),我認爲如果要擴展學習經典紅黑樹的話需要結合《算法導論》的第十三章和TreeMap的源碼,除此之外,暫時沒有發現參考學習經典紅黑書更合適的材料。

除此之外,《算法》中沒有對動態規劃和貪心算法的介紹,這一部分在《算法導論》的第十五章和第十六章有講解,不過動態規劃和貪心算法類的Leetcode題目在我看來還是比較難的,需要結合大量的練習纔行。

以上,對於 基礎的算法學習 就比較全面了,下面我們來討論一些問題作爲補充:

《算法導論》需要讀嗎?

我認爲《算法導論》真的是非常合適的算法學習參考書,由於之前我也帶着“黑皮書”讀起來比較困難的想法,所以只把它作爲了補充閱讀,沒有以它的內容爲準,如果現在讓我重新選擇,我會把它作爲主要參考書而其他作爲補充閱讀。

《算法導論》它不侷限於語言,其中的代碼內容是僞代碼實現,所以任何語言的學習者都是合適的。而且,它會用單獨的章節來介紹算法中常用的策略,如分治法等,此外在數據結構中創建哨兵節點的技巧也在鏈表章節中也描述。我認爲它的前十六章加上第二十二章用來學習基礎的算法已經足夠了。開篇我說這本書像雞尾酒,因爲 它還擴展了高級數據結構和更加深入的算法知識,如斐波那契堆、van Emde Boas 樹、數論算法和NP相關的知識等,所以,它的知識更加全面,面向的讀者範圍更廣。我認爲作爲普通的算法學習者,一定要把握好學習的度,因爲算法本身相對更加耗費腦力和時間,鑽牛角尖式的學習在工作和生活間協調起來是不容易的,而且在算法導論中確實有一些複雜的證明和推導存在,可以選擇性的跳過,因爲我們的學習並非研究和探索,這樣降低了難度也提高了學習效率。

《Hello 算法》是怎樣的一本參考書?

《Hello算法》是一本基礎的算法書,它的作者是也是Leetcode上劍指Offer系列題解的作者,這本書的知識基本上覆蓋了刷LeetCode所需要的知識,它在內容深度上沒有做擴展,像紅黑樹這些,也正如它的前言所述:它是一本能夠讓你避免讀大部頭便具備基本刷題能力的書,如果大家在短時間內想補足算法知識的話,參考這本書足夠了,但是深入的學習是必要且無法被替代的。

對於只想刷題的同學該怎麼學習?

我覺得可以直接參考高頻題目的題單 分類 先刷起來,然後根據題目,發現缺少的知識進行補足。這樣相對更加高效,因爲Leetcode具有技巧性和規律性,結合大量的題目練習是最好的方式,反而如果先啃完大部頭再回過頭刷題可能效率不夠高,而且這樣也不能得到預期的收益,因爲這些書它並不是教你如何刷題的。


以上內容對於找到適合自己的算法學習路線我認爲已經足夠了,接下來是我在算法學習中實踐過的學習方法:

艾賓浩斯學習法

我認爲學習某項技能,不僅侷限於算法的學習,最終目的在於形成對它的長期記憶,並不是僅僅保留印象,而形成長期記憶的方法也非常簡單:即頻繁而有效的重複刺激,像我們的母語和一些生活習慣(刷牙、打扮和繫鞋帶等)之所以不會忘記是因爲我們每天都在反覆的刺激大腦如何運用,乃至最後都形成了肌肉記憶。總之,學習結合規律的複習,並歸納總結,便可以克服遺忘,達到溫故知新的結果

艾賓浩斯遺忘曲線,即人對於知識的遺忘速度遵循 "先快後慢" 的原則。學得的知識在一天後,如不抓緊複習,很快就只剩下原來的 25%,而隨着時間的推移,遺忘的速度會減慢,遺忘的數量也隨之減少。

如果想有效抵抗遺忘,最好的辦法就是進行規律的複習(每 5 分鐘、30分鐘、12小時、1天、2天、4天、7天、15天、1個月、3個月、6個月)。

艾賓浩斯遺忘曲線是大家都熟悉的概念,但是我幾乎沒有發現我的同學採用類似的學習方法。如果不是在朋友的推薦下,我也不會去改變自己的學習方式,在我實踐過之後,收穫很大,所以也分享給大家,下面是部分我用來記錄學習和複習的艾賓浩斯表格:

image.png

我並沒有完全照搬它的複習時間,而是採用了2小時、12小時、2天、7天、15天、1個月和3個月這樣的時間間隔,其中表格中記錄的是學習日期,綠色表示按時完成複習,紅色表示沒有按時複習。

採用這個學習方法我認爲需要始終堅持 “循序漸進,按部就班” 的學習理念,不能一時圖快而在短時間內學習過多知識,否則它會帶來長時間的複習壓力,也不能採取斷斷續續學習幾天就休息一陣子的方式,而是真正地讓學習成爲一種習慣,慢慢地積累達到知識穩步增長的目的,這更像是投資的複利。

這種學習方法完全打破了我之前“從來不復習,永遠看新的”的學習方式,而且不復習經常會帶來“這個東西我看過,但是我忘了”的困擾,導致最後學完什麼都沒有剩下的局面,並且從採用這個學習方法之後,以“手寫線段樹”爲例,真得可以信手拈來,像“肌肉記憶”一樣,所以規律的學習和複習是很有必要的。需要注意的是:這種學習方式需要耐心、毅力和自制力的輔助,並根據自身記憶情況進行合理的調整,達到合適的學習和複習模式,否則很容易在遇到長假休息時導致學習計劃夭折。

Over

所有內容到這裏就已經結束了,文末是一些優秀的參考文章和題單,希望能幫助大家在算法學習上少走一些彎路,最後祝大家學得開心~


巨人的肩膀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章