前幾天在csdn後臺收到了一個讀者的留言,他有很多很多學習資料,但就是不知道學什麼、也不知道該從何學起,學了很久還只會寫個Hello World。
根據我的經驗,除了這個問題,很多同學應該還會遇到如下問題:
爲什麼有的人學了很久很久編程,還是隻會寫一些簡單的算法題?
學了幾個月編程,還沒有寫出超過100行的小項目。
好不容易看完了一本書,合上卻發現前面的內容全忘了。
我相信,很多學習編程的同學都想切實地做出一個項目,比如可以真正被使用的軟件。
可是很多人搞來搞去,永遠都只會寫控制檯程序,不是動態規劃就是貪心。
以上現象你中招了嗎?
遇到這樣的現象不要怕,你不是一個人,我剛學編程那會兒也是這樣的。不僅是我,我相信還有很多同學是這樣,那到底是什麼隱形的力量在阻止我們學會編程呢?
我總結了以下幾個原因,如果你中招了,可以考慮參考一下解決方案哦。
先問大家一個問題,學習編程的你有沒有刷過OJ(OJ指在線編程練習)。
我相信大部分人都有過刷題的經歷或是現在正想開始刷題。
我曾經也是,一閒下來就迫不及待地打開一些刷題網站不停刷題,今天刷動態規劃,明天刷最短路......爲了AC一道題,我曾一天都忘了喫飯。
直到有一天,我突然發現了一個問題——我究竟爲什麼要刷題?
不知道各位刷題是爲了什麼。
提升編程能力?
如果是這樣,那麼問題來了......
刷題真能提升編程能力嗎?
如果能。
那麼問題又來了......
什麼是編程能力?
你可能又會說:“會刷題!”
噢!恍然大悟,原來刷題是爲了提升編程能力,編程能力提升以後刷題就更容易了......
這好像是個無解的問題 ......
不知道各位有什麼高見沒有,如果有,請務必留言告訴我,謝謝!集思廣益嘛。
好了,我來講下我對刷題的理解吧。
我先講一個我和ACM的故事。
首先解釋一下什麼是ACM,ACM的英文全稱是International Collegiate Programming Contest,簡單來說就是一個大學生程序設計競賽。計算機學院和軟件學院的同學肯定知道這個競賽,也有很多人蔘與。
由於我是被調劑到計算機專業的,所以在大學前對計算機的相關行業並不是特別瞭解。在我懵懵懂懂地入學時,學校有各種課外社團宣講招新,其中有個社團就是由ACM愛好者組成的。聽完那場宣講會我只有一個感覺:牛逼的人都參加ACM。
對,我並不是因爲愛好,只是覺得參加了ACM就比別人懂得多。這種心理就和高中參加課外補課班的感覺一樣,有種私下裏偷學了很多知識,看誰都是憨憨的感覺。
所以我報名參加了ACM,可能是因爲我大一的時候編碼能力太弱,沒入選,也就和ACM失之交臂。
我並不是因爲當初沒被選上參加ACM而“懷恨在心”,纔在這裏吐槽。我並不是吐槽ACM不好,其實參加ACM對提升思維能力是很有好處的。
我想吐槽的是很多人無理由地參加ACM——從衆心理。很多人生怕別人參與了ACM就比自己學得多,所以別人做什麼他就要做什麼,就像人人都說機器學習牛逼,你就跟着去學,結果什麼都學不好。
學習任何一個技能,要麼是因爲愛好,能從中獲得快感,要麼能提升自己。
學編程,刷題一定是要的,但一定不是盲目地刷。
第一遍刷題是將你學習的算法和數據結構理論變成實踐,強化知識。
刷題有助於我們將抽象的算法轉化爲具象的代碼實現,讓我們明白其中的原理。
比如你用C++、Java或是Python把9大算法都實現一遍以後,你就知道其中的原理,之後就沒必要再繼續刷同類型的題了。
我們需要培養自己的技術選型能力、方案選擇能力,具體是指:
當遇到實際業務和需求的時候,你需要知道在什麼場景下使用什麼樣的數據結構和算法,然後通過查詢或調庫使用這些算法。
技術是服務於業務的,編程是爲了解決問題。
當然,以上言論都是我自己的理解,你可以有不同的看法,但是我不接受反駁。
第二遍刷題是在你找工作面試的時候將各種算法寫給面試官看。
爲找工作刷題無可厚非。就像高考一樣,我們需要一套選拔的機制,面試中手寫代碼的過程就能直接體現一個人的代碼能力。爲了拿到一個好的offer,你必須刷題,關於刷題的事情我也在我之前找工作的系列文章中提到過,感興趣的同學可以自行查看,此處就不過多套路。
以上兩點就是我自己“刷題”方式,我大學時就在這兩個時期全身心地投入刷題,其他時間我就做其他的事情了,做什麼事情呢?後文我們繼續聊。
總結一下就是,不管是編程還是任何其他學科的學習,我們一定要明白自己學習的意義,如果僅僅是因爲從衆,而根本不知道自己爲什麼要做這件事情,那麼還是先搞清楚自己爲什麼要做,否則很多時候都是在做無用功。
死磕原理指的是什麼?
舉個簡單的例子。
大家要是學過樹或圖的遍歷算法,肯定知道最基本的兩個遍歷方式:
DFS和BFS(這裏有北外的同學嗎?)其實就是深度優先遍歷和廣度優先遍歷。
不明白沒關係,我先簡單解釋下。就拿最簡單的二叉樹舉例,下面是一個二叉樹。
如果要從A點出發遍歷完所有的點。
深度優先遍歷就是“不撞南牆不回頭”,從A點一直往下走到盡頭才往回走,在發現新路後又繼續往下走,所以遍歷順序是:A-B-D-E-C-F-G。
寬度優先遍歷就是“先走完上一層再走下一層”,所以遍歷順序是:A-B-C-D-E-F-G。
那麼問題來了,死磕原理和二叉樹遍歷有毛關係?
不瞞您說嘞,關係大着呢...
我們把二叉樹比喻成一個知識體系。
第一層A代表了你所學的所有的專業知識。
第二層代表大學本科階段的各個科目,比如B有可能是Python課程,C有可能是算法和數據結構,當然還有很多其他的科目,如高數,英語等,我就不一一列舉了。
試問大家一個問題,如果掛了幾科第二層的課程,能畢業嗎?
好像是不能畢業的。
那現在假設某個同學第二層的課程全部通過得以順利畢業,他將進入到研究生階段。
這時候他會選擇一個“方向”繼續“深造”。
請注意上面加粗的詞語。
本科生階段是面向於“面”的教育,就是啥都教給大家;
研究生階段是面向“點”的教育,是建立在本科階段對自己專業的整個體系有了初步瞭解後做出的選擇,他可能會選擇自己感興趣的方向繼續學習。
所以,如果他選了B方向,那麼他將繼續攻克D和E。
和學習編程一樣,第二層就像是你肯定要學習的編程語言、算法、數據結構等學科,學好它們才能寫出一個靠譜的程序。
再往後的第三層,是你可能在研究生階段主攻的機器學習、人工智能等知識,或是架構方向、圖像處理等方向。
”死磕原理“的定義漸漸清晰了:
我們不要一個衚衕走到黑,初學編程的時候,一定要多多瞭解各個學科之間的聯繫。
人的精力是有限的,如果你一直在一門課上搞啊搞的,缺點有三:
你很可能很久都寫不出來一個像樣的程序,自信心受到打擊;
你可能會做很多無用功。一些學科需要其他學科的知識做鋪墊,而僅僅在一門課中閉門造車會浪費大量的時間;
你可能會陷入造輪子的境地。
那到底有什麼好的方法可以學習編程嗎?
有的!
還是舉個例子,我們學數據結構的時候不是有很多已經封裝好了的數據結構嗎?比如C++中的Vector,Python中的dict、list等,你們有看過它們是怎麼實現的嗎?
如果你看過Vector的實現方式,你肯定會感嘆它的動態擴展內存有多麼巧妙。
你自己能把這個數據結構寫出來嗎?
注意,上面加粗的字,正是很多人編程學得慢的重要原因之一。
什麼知識都要強調自己能寫出來。
我剛學數據結構那會兒也是這樣想的,當時我在心中定下一個宏大的目標,要自己實現課本上所有的數據結構。所以我花了很長時間去寫一些現有的數據結構,也成功地寫出了一些,如平衡二叉樹、紅黑樹......
可真的花費了我很多時間......
我又陷入了沉思......
可以直接用的東西,我爲什麼要去寫呢?
初學的時候,我建議大家還是面向“面”去學習,我們可以瞭解某個數據結構的內部原理,但先不要嘗試自己去實現。遇到一個場景,我們知道選擇什麼樣的數據結構去使用就好。然後學完原理之後,大家就可以學一些算法和一些小的框架了。
不瞞您說,如果只是一味地學習編程語言語法和刷題是學不會編程的。
一定要去看一些框架、做一個項目,然後運用你現在學習的這些知識,把它們融合起來。在實踐的過程中你會發現自己還欠缺很多其他的知識,這時你再去有針對性地學習,知識轉化率才高。這個項目可以是一個Web,一個App,或者一個爬蟲系統。
“一口喫成一個胖子”的貪婪心理也是一個阻礙大家學習編程的絆腳石。
舉個例子:
我們學習一個框架或者學着做一個項目的時候,可能文檔或課程說明上會寫“學習本課程之前需要先會Java、數據結構、數據庫、操作系統等知識”。
但你肯定不是全會啊,怎麼辦?立馬放下這個項目去學習上述課程?
這就是典型的“一口喫成一個胖子”的表現。我們做項目的時候不要怕自己這不會,那也不會。不會先上谷歌百度查一下,或者先直接參考別人的代碼,然後自己把問題記下來,後面再去深究。
當你成功做出第一個項目後,你就會大受鼓舞,再去做第二個、第三個,然後就起飛了。
萬事開頭難。
一定要採取項目驅動式的學習方法,不管是編程還是其他科目,我們除了系統學習,還一定要建立一條“發現問題,解決問題”的學習路徑。
一開始做項目,不用自己去做,先找個別人的項目來看。如果找不到項目,可以私我分享你喜歡的類型的小項目,從最基礎的開始一點點的來
新手們剛剛開始學習的時候也不要好高騖遠,認真走好每一步的基礎,只有踏實的一步一步走來,才能進階的更好更高。想要進階更多的可以關注我的主頁,學習更多。