前言
此文對我影響很大,分享出來給大家,願大家早日成為大神。
1)不要完美主義!
我觀察到的大多數同學犯得最最最最大的“錯誤”,就是在學習上“完美主義”。乃至后續很多其他的問題,在我看來都和這個問題是直接相關的。
舉個最經典的例子,也是我經常舉的例子,背英語單詞(在這里我們先不聊背英語單詞是不是好的英語學習方法,我們只看如果我們想要背英語單詞的話,應該怎么背)。
我發現很多同學拿着紅寶書,第一個list都沒翻過去就放棄了。這是因為每天背完第一個 list 以后,第二天會發現:第一個list還是有很多單詞沒掌握,然后就繼續背第一個 list。然后一周后,發現自己第一個 list 都搞不定,覺得英語好難,徹底放棄了。這就是“完美主義”:不把第一個 list “徹底”掌握不肯繼續前進。這樣是不對的。背了一個list,能多記一個詞,都是進步。就算一個詞都沒記住,模糊有了印象,也是一種進步。
我們不應該過度着眼於我們還不夠完美。
學習不是要么 0 分,要么 100 分的。80 分是收獲;60 分是收獲;20 分也是收獲。有收獲最重要。但是因為着眼於自己的不完美,最終放棄了,那就是徹底的 0 分了。
仔細想,這種“完美主義害死人”的例子特別多。我看到過很多同學,其實是在學習的路上,被自己的“完美主義”逼得“放棄了”——由於學習中有一點沒有做好,遭受到了一點點挫折,最終就放棄了整個學習計划。每個人都一定要接受自己的不完美。想開一點:我們都不是小升初考了滿分,才能上初中的;也不是中考考了滿分,才能讀高中的;更不是高考考了滿分,才能念大學的;將來也不會是大學所有科目都是滿分,才能出來工作。不完美其實是常態,根本不會影響我們學習更多更深入的內容。但是在自學過程中,很多同學卻要求自己在自己制定的每一步計划中都達到“完美”,才進行下一步。最終結果,通常都是“放棄”:(
可能有的同學會跳出來反駁我:學習當然要認真啊!在這里,我必須強調,我所說的“不要完美主義”,和“學習認真”是不沖突的。
什么是“完美主義”,什么又是“囫圇吞棗”,這是一個“度”,每個人其實不一樣。不要“完美主義”,不代表學習可以草率前行。
每個人都必須要找到適合自己的學習節奏。我的經驗是:在一些情況下,問自己一句:是不是自己又犯“完美主義”的毛病了:)
2)不要過度“學習路徑依賴”,學習要沖着自己的目標去。
什么意思?就是現在信息太發達了,對於大多數領域的知識,網上會有很多所謂的“學習路徑”。我不是說這些學習路徑沒有用,但是不能“過度”依賴這些所謂的學習路徑。
比如,很多同學想學機器學習,大多數學習路徑都會告訴你,機器學習需要數學基礎。於是,很多同學就轉而學習數學去了,非要先把數學學好再去學機器學習。可是發現數學怎么也學不好(在這里,可能完美主義的毛病又犯了),而機器學習卻一點兒都沒學。最終放棄了機器學習,非常可惜。
其實,如果真正去接觸機器學習,就會發現,至少在入門階段,機器學習對數學的要求沒有那么高。正因為如此,我一直建議:只要你在本科接觸過高數,線數,概率這些科目的基礎概念,想學機器學習,就去直接學習機器學習。學習過程中發現自己的數學不夠用,再回頭補數學。在這種情況下,數學學習得也更有目標性,其實效果更好。
類似這樣的例子還有很多,很多同學想學習做 iOS app,就先去精通 Swift 語言,或者想做android app,就先去精通 java 語言。在我看來大可不必。以我的經驗,只要你有一門編譯型語言基礎,大概看一下這些語言的基礎語法,就可以直接上手 iOS 或者 android app 的開發了。先能做出一個最基本的 app,在這個過程中,就會意識到語言特性的意義,再回頭深入研究語言也不遲。此時還能結合真實的開發任務去理解語言特性,比沒有上手 app 開發,抽象地理解語言特性,有意義的多。
雖然我一再強調對預算法的學習,語言不重要,但還是有很多同學表示,要先把 C++ 學透,再回來把課程中的算法學好。這是完全沒必要的。事實上,在我的這兩門課程中,我看到的收獲最大的同學,是那些能夠把課程中的算法思想理解清楚,然后用自己熟悉的語言去實現的同學:)
依然是:不要“過度”學習路徑依賴,什么叫“過度”,每個人的標准不一樣。每個人都需要尋找自己的那個“度”。
3) 不要迷信權威的“好”教材。
不是說權威教材不好,而是每一本教材都有其預設的讀者群,如果你不在這個預設的讀者群的范疇里,教材再好也沒用。最簡單的例子:再好的高數教材,對於小學生來說,都是一堆廢紙。
我經常舉的一個例子是《算法導論》。我個人建議如果你是研究生或者博士生,已經有了一定的算法底子,才應該去閱讀《算法導論》,我在我的課程的問答區,也談過如何學習使用算法導論。
但是對大多數本科同學,尤其是第一次接觸算法的同學,《算法導論》實在不是一個好的教材。
但很可惜,很多同學在學習中有上面的兩個毛病,既過度路徑依賴,別人說《算法導論》好,學習算法要走學《算法導論》這個路徑,自己就不探索其他更適合自己的學習路徑了,一頭扎進《算法導論》里;同時還“完美主義”,對於《算法導論》的前幾章,學習的事無巨細,但其實接觸了很多在初學算法時沒必要學習的內容。最后終於覺得自己學不下去了,放棄了對“算法”整個學科的學習。認為算法太難了。
誠然,算法不容易,但是,一上來就抱着《算法導論》啃,實在是選擇了一條完全沒必要的,更難的,甚至可能是根本走不通的路。對於一個領域的學習,了解市面上有什么好的教材是必要的,單也不能迷信權威教材。每個人必須要去探索學習如何尋找適合自己的學習材料。
4)不要看不起“薄薄”的“傻”教材,這些你看不起的學習材料,可能是你入門某個領域的關鍵。
很多同學問我最初學習算法的是什么教材,我告訴他們是這本教材:《算法設計與分析基礎》 。在這里,我完全沒有推薦這本教材的意思。事實上,現在我有點兒“鄙視”這本教材。因為我在學習它的過程中,發現這本教材有很多錯誤(幫助它糾正錯誤其實也提高了我的水平:)
當然,現在這本書的版本可能也和我當時學習的版本不同了,大部分錯誤應該已經糾正了。)但它確實是我的一本很重要的算法啟蒙教材。
關鍵原因是,它夠薄。
在大多數時候,如果有人問我教材推薦,基本上我的回答都是,如果是入門水平:隨便找一本在京東,亞馬遜,豆瓣上,評分不太差的“薄”的教材,就 ok 了。
在這里,關鍵字是夠“薄”。
因為“薄”的教材能讓你以最快的速度看完,對整個學科有一個全盤的認識:這個領域是做什么的?解決什么問題了?整體解決問題的思路是怎樣?解決問題的方法大致是怎樣划分的?一些最基礎的方法具體是怎樣的。這些在初學階段是至關重要!是讓你全盤把握整個領域脈絡的。
雖然通過這么一本薄薄的教材,你的脈絡把握肯定不夠全面細致,但比沒有強太多!我看過不少同學,一上來學習《算法導論》,關於復雜度分析的筆記做了好幾頁,然后就放棄了,可是連什么是動態規划都不知道。這樣完全沒有對“算法”這個領域有全面的認識,甚至可以說根本沒有學過“算法”!
先用薄教材入門,再找“厚”教材,細細體會其中的細節,是我百試不爽的學習方法。
另外,在這里,我還要強調“入門教材”,很多教材雖然夠“薄”,但不是“入門教材”。大家要注意。
5)不要迷信單一教材。
很多同學理解了要找“薄”教材入門的道理,卻還是非要我推薦一本具體的“薄”教材,說實話,很多時候這讓我有點兒哭笑不得。
因為我隨便推薦一本,我確實不敢保證它是“最好的”,“最適合你的”,但是各個領域那么多教材,我又不可能都一一看過,一一比較過。
最最重要的是,我的學習經驗告訴我,在大多數情況下,學習不是一本固定教材可以搞定的。
非要找到一本“最適合自己的”教材,然后就一頭扎進去,其實是不科學的。我印象很深刻,我讀本科的時候,那會兒申請了一個項目,要做一個網站(那時候服務端都用 ASP.NET ),我一口氣從圖書館借了 10 本 ASP.NET 的教材,然后以一本最薄的書為主干去看,發現這本書介紹不清楚的概念,馬上就從其他書里找答案。
通常不同的作者對同一個事物從不同的角度做解讀,是能夠幫助你更深刻的認識一個概念的。基本上一個月的時間,我就從一個完全的網站搭建小白,做出了這個項目需要的那個網站。
這個習慣我一直延續,研究生的時候,對什么領域感興趣了,第一件事就是到圖書館,借十本相關書籍回來翻看。
但是,大多數同學喜歡僅僅扎進一本書里,一旦選定了自己的學習材料,就對其他材料充耳不聞,甚至是排斥的心理。這種做法,一方面又是“完美主義”的表現——非要把這本教材學透;另一方面,其實也是“犯懶”的表現,不願意多翻翻,多看看,自己多比較比較,自己去尋找最適合自己的材料,一味地盲目相信所謂“大神”的推薦,殊不知,這些推薦,不一定是更適合自己的材料;更何況,還有很多大神,明明是靠不出名的“薄”教材入的門,但給別人做推薦的時候,就突然變成自己是算法奇才,自幼閱讀《算法導論》而所成的神話了:)
6)實踐
前面說了很多和教材選擇相關的話題,但對於計算機領域的學習來說,教材的意義其實遠遠小於實踐的意義。如果僅僅是看學習材料就是學習的話,那么慕課網的視頻后期處理人員就是水平最高的工程師了。因為每段視頻,他們都需要看一遍。但是,很顯然,僅僅是看視頻,是無法學到知識的。
對於計算機領域的學習來說,真正動手實踐去編程是異常重要的。怎么誇大其中的作用都不過分。
這就好比學游泳,必須下水去游泳;或者學開車,必須親自上路。
否則你說的再頭頭是道,一個小學生文化水平的人,只要他開過車,游過泳,都能在這兩個領域瞬間秒殺你。
很多同學都說我的算法講得好,其實,我一直認為,這其中的一個最簡單的秘訣就是:我帶領大家把大多數算法都非常細致的實現了一遍;或者對其中的應用進行了非常具體的實踐。
反觀大多數高校教育,對於算法或者機器學習這種一定程度偏理論的學習,通常非常不強調實踐。最終的結果是學習者只是接受了很多抽象的概念,但對其中具體的實現細節,卻是雲里霧里。
我見過太多同學,都明白什么是 O(n^2) 復雜度,什么是 O(nlogn) 的復雜度,卻問我對於 100 萬的數據規模,為什么自己的選擇排序運行起來就沒反應了。答案很簡單:O(n^2) 的復雜度太慢了,100 萬的數據規模太大了,一般家用計算機轉選擇排序一時半會兒是轉不完的。這些同學一定理解 O(n^2) 的算法比 O(nlogn) 的算法慢,卻沒有真正實踐過,不知道這個差距到底是多少。
在我的課程中,經常遇到有些同學提出這樣的問題:這個算法的某句話(或者某段邏輯),為什么要寫成 A 的樣子,而不是 B 的樣子?這種問題其實很好,但我覺得解決方法也很簡單,實際的去把算法改寫成 B 的樣子,實際的運行試試看,看會發生什么。如果發生了錯誤,仔細分析一下,為什么會有錯誤?如果沒有錯誤,具體比較一下:A和B兩種不同的寫法,為什么都正確?又有什么區別?
真正的學習上的提高,就發生在這個過程中。
我當然可以告訴給同學們一個結果,但是自己親自實踐一遍,相比閱讀我給出的一個答案,自己對其中問題理解的深刻程度,是完全不可比擬的。
7)debug非常非常重要。
我看到的另一類“經典”問題就是:老師,這個代碼為什么錯了,然后貼一大段代碼。這種問題背后,依然是,透露着學習方法的不對勁:提問的同學懶得 debug 。
在計算機領域,debug 近乎和實踐是一個意思。如果只是把材料上的代碼“抄”一遍,這不叫實踐,這叫抄代碼。小學生也能做。但是“抄”一遍,不小心沒抄對,發生了錯誤,然后自己一點一點調試,找到錯誤的根源,這叫真的實踐。小學生不能做。(當然,我更推崇的是:自己理解了算法的邏輯,按照自己的理解,把算法寫出來:)
不過很多同學不喜歡 debug,我當然理解。其實誰都不喜歡 debug ,但是,debug 才是最重要的能力。(通常在一個領域里,你最不喜歡做的事情,就是這個領域的核心競爭力:)是計算機領域異常重要的一項技能。我見過的所有計算機領域的“高手”,不管是在哪個細分領域,都無一例外,是個 debug 好手。我經常告訴大家,在實際工作中,其實 debug 的時間要占你真正編程時間的 70%。如果你做一個項目,根本不需要 debug ,要么是你的項目對你來說太簡單了,要么是你根本沒有接觸到這個項目的核心。
debug 不僅僅是找到代碼錯誤,解決錯誤的手段,其實更是一個重要的學習手段。通過 debug,看看自己寫的程序執行邏輯,哪里和自己設想的不一致?再回頭看自己哪里想錯了,或者想漏了,分析一下自己為什么想錯了,或者想漏了,等等等等,依然是,進步就是發生在這個過程的。
在我的算法課程中,很多同學對遞歸想不明白,我的建議都是:用一個小數據量,一步步跟蹤程序,看看程序到底是怎么運行的。通常這么做,1 個小時的時間,就足以讓你深刻理解遞歸程序的運轉邏輯。可是,很多同學懶得花這1個小時的時間,最終的結果是,花了一個下午,對着代碼生看,硬想,最終還是沒有理解程序的運轉邏輯。
8)量變到質變。
還有很多同學,對於算法的一些問題,會問:老師,你是怎么想到用這樣的方法的?對於這類問題,我的回答一般都是:你見的還不夠多。
不知道是不是受高中階段學習的影響,有一些同學特別執着於就着一個單一的問題,尋找其中的“解題路徑”。當然,我不是說這是完全錯誤的,但也有一個“度”。
我的經驗是:與其把時間花在這里,不如去見更多問題。
比如動態規划,是算法學習的一個難點,很多同學在學會了背包問題的解法之后,總是執着於去追尋:是怎么想到這種狀態定義的方法的。可能是我個人水平有限,我無法清楚地解釋是如何想到這種狀態定義的方法的。但是我的經驗告訴我:再去看,去實踐 100 個動態規划相關的問題,然后回頭看背包問題,你會發現這種狀態定義的方式非常自然。
僅僅對着一個問題思考,很多時候都是死胡同。你見識的還不夠多,就不足以幫助你總結出更加“普遍”的問題解決的規律。當你見得足夠多的時候,一切就都變得很自然,所謂的“量變到質變”。
不過,大多數同學在這個環節都會“犯懶”,企圖通過一個問題就理解問題的本質,這其實和企圖通過一本教材就精通一個領域的想法是一樣的,是不現實的,不可能的。同時,這里又包含着學習過程中的“完美主義”的思想,遇到一個問題一定要把它想的無比透徹。但是我的經驗告訴我:大多數問題,其實都是需要“回頭看”的。隨着你對一個領域理解的越深入,回頭再去看那些曾經的問題,都會產生新的視角,對於很多曾經想不明白的問題也豁然開朗。這也是“進步”的根源。如果卡在一個問題上不前進,不給自己“回頭看”的機會,甚至最后是放棄了,就什么也沒有學會了。
所以,很多時候,你發現對一些問題“百思不得其解”,或許不是因為自己“笨”,而是因為“還不夠努力”:)
9)最后,一定要相信時間的力量。
有一天,在我的一個算法課程群里,有個滴滴的后端大神發招聘,結果大家七嘴八舌的就議論開了,大致主題思想就是:自己什么時候能夠成為滴滴的后端大神。這位滴滴的后端大神今年 32 歲;大多數議論的同學,其實連 22 歲都不到。我告訴他們,其實 10 年后,你們就是大神。
這其實很好理解,回想十年前,也就是 12 歲的你,和現在的你比較,是不是天壤之別?如果把你扔到一堆 12 歲的小朋友中間,22 歲的你是不是就是個大神?同理,32 歲的人,已經在業界摸爬滾打了那么多年,扔回到22歲的大學生中間,當然是大神:)
很多時候,所謂的“大神”並不神秘,很多時候,仔細觀察,會發現時間有着不可磨滅的作用。只要你沒有虛度時間,每天都在進步,通常結果都不會太差的。如果再加上一點點機遇,可能就不僅僅是大神。
願大家也早日成為大神。
End
本文作者為 liuyubobobo,算法大牛,ACM亞洲區獎牌獲得者,現居美國,創業者。bobo老師對我影響極大,我的算法入門和進階都是靠他的指導,希望此篇文章對大家有幫助~
願大家也早日成為大神。
樂於輸出干貨的算法技術公眾號:「五分鍾學算法」。公眾號內有 100 多篇原創技術文章、精美動畫配圖,不妨來關注一下!