學好演算法對一個程序員來說是必須的嗎?如果是,至少應該學到哪種程度?

對於一個即將找工作的新手程序員來說(安卓開發)?


謝邀。

首先,對於大部分程序員而言,在工作中不是必須的,但是你要找工作,特別是剛畢業參加校招的學生,想進入一些比較大的公司(BAT之流),是必須要學好演算法的

此外,我認為在提高自我技術水平的過程中,比如去閱讀一些優秀的代碼的時候,也是需要演算法功底的,就像去看leveldb、redis源碼的時候,起碼得知道跳錶是個啥吧,看Linux內核文件系統的代碼得知道紅黑樹是個啥吧。

再就是有一個很重要的影響:演算法學的好的話,不論對你思考問題的方式還是對你編程的思維都會有很大的好處。

另外關於刷題的網站還是首推Leetcode。

如果有一些演算法基礎的話,推薦Codeforces。

至於資料書籍的話,其實沒有太多要求,網上的資料很多,隨便谷歌一下就能找到很多詳細的資料。

演算法導論的話不推薦,不推薦初學者看。這本書是本神書,但是這本書的門檻比較高,需要有一定數學基礎和演算法基礎的人去研究,如果你沒有一定的基礎或者對演算法狂熱的學習興趣,你很難啃下去。

改了一下知識列表的結構,分了下類,可能更加清楚一點。這裡面基礎是我覺得必須應該掌握的,中等的是有如有餘力最好學習的,高級的可以了解,可以了解一下,對於個別感興趣的可以深入學習一下。

這裡面僅僅根據我個人的學習經歷去區分難易度,不代表知識本身難易度的精確定位。另外如果大家有什麼比較好的補充或者一些問題,可以私信我,我再修改~

1.【數據結構部分】

數據結構我覺得在演算法這個概念里的地位是非常重要的,因此還是花一定的精力去學習和練習,看完理論可以刷題,刷完題可以看一些工業級的代碼,比如STL源碼等,去了解各種數據結構現實應用。

【基礎】

鏈表(單雙向鏈表、循環鏈表等)、隊列(單雙向隊列)、棧、大/小頂堆、多叉樹、排序二叉樹(主要熟悉樹的前中後序遍歷)

【中級】

並查集、樹狀數組、RMQ、字典樹、跳錶(非常好用的數據結構,被leveldb、redis等key-value資料庫採用)、B/B+樹(文件系統中非常常用的數據結構了)、AVL樹(平衡二叉樹、看懂了為後面的伸展樹和紅黑樹做基礎)、線段樹(在logn的時間級別內解決區間問題)

【高級】

DLX數獨問題、AC自動機(KMP+字典樹的結合,在解決大量字元串模板匹配問題上非常好用)、樹鏈剖分(高級數據結構,解決樹上的路徑更新問題)、伸展樹、紅黑樹(非常出名的數樹形據結構、比較複雜,Linux內核中的文件系統基於這個實現)

2.【圖論部分】

圖論的話主要是DFS和BFS這兩個搜索策略的學習,多熟悉熟悉,不同的實現方法都有什麼,比如遞歸的寫法和非遞歸的寫法等等。此外就是最短路的問題,至於一些網路流、圖匹配等問題,因為不是打競賽,僅僅是考慮學習,可以不需要深究。

【基礎】

DFS(深度優先遍歷)、BFS(廣度優先遍歷)、拓撲圖、最短路問題(Dijkstra)、拓撲排序問題

【中級】

最短路問題(Bellman-Ford、SPFA等)、最小/大割問題、最小生成樹、歐拉迴路、最近公共祖先(LCA)

【高級】

網路流問題、二分圖匹配問題

3.【字元串部分】

字元串的問題其實也在日常應用挺多的,重點了解一下KMP和Hash。

【基礎】

字元串哈希(Hash)、迴文問題、子串問題

【中級】

KMP演算法

【高級】

後綴數組、AC自動機(前面說到過)

4.【數學部分】

數學問題其實沒有太多好說的,在學校的同學們還是盡量學好高數、概率論和線性代數吧,這個是一個積累的問題,以後如果進一步的研究和學習,數學肯定是不能太差的,這裡就不分類了,只列舉一些簡單的數學問題。

快速GCD,最大公約數、擴展歐幾里得、中國餘數定理、求逆元、素數問題

5.【動態規劃部分】

動態規劃可以說在各種公司的面試中深受廣大面試官喜愛,動規(DP)主要還算是一種解決問題的思想,並不是像一個數據結構模型的成型演算法,學好的話很難,但是學好動規可以說對你思考問題的方式有很大的提高,這裡列一些常見的動規問題的分類。

【基礎】

背包問題(0/1背包、完全背包)、最長遞增字串問題(LIS)、最長公共子序列(LCS)

【中級】

區間DP、樹形DP、數位DP、概率DP、狀態壓縮DP

【高級】

複雜的DP(經過各種數據結構優化或者各種開腦洞的DP)

6.【幾何問題】

這個我有點忘了,本身之前學習的少,改天查查資料再補。

7.【其他】

二分查找、貪心問題、各種排序(冒泡排序、歸併排序、快速排序、堆排序等)、分治。

最後,也是最重要的:

演算法的學習不只是理論的支持,更需要你不斷的在理論的基礎上去code,去思考。


看到題主是學習移動開發的,學習演算法的目的是找工作需要,應該是應屆生。

那麼,演算法學習的最低目標就是通過校招求職的筆試、面試。

具體如何去備考呢?牛妹詳細介紹一下校招筆試面試的演算法通關秘籍:

1、熟悉在線判題系統(Online Judge)

現在多數互聯網IT企業的筆試編程題是在線判題,OJ系統跟本地編譯存在一定的區別,比較常見的區別舉幾點:

· OJ需要循環輸入輸出

· 注意輸入輸出的格式

· 不提供測試用例

· 測試用例會有多組

熟悉在線判題系統對於筆試非常重要!非常重要!非常重要!

推薦一個視頻和帖子供參考:

· OJ(編程在線判題)入門介紹

· (經驗貼)那些年在編程題中踩過的坑_技術交流

2、熟悉常考演算法題型

校招最常考的演算法類型主要是以下幾類:

· 暴力枚舉

· 動態規劃

· DFS/BFS

· 數學問題

· 模擬現實

· 貪心演算法

· 字元串演算法

具體可以看一下我之前的一個回答:

https://www.zhihu.com/question/24964987/answer/200681301

3、多多練習相關題目

演算法是絕對需要刷題的,大家最常刷的是這兩個題庫:

· 劍指Offer

· leetcode在線編程

除此之外,還可以刷一下企業的歷年筆試真題

· 阿里巴巴

· 騰訊

· 百度

· 京東

· 網易

· 華為

· 美團

· 滴滴

· href="https://www.nowcoder.com/contestRoom">更多:100家名企筆試真題

如果你的演算法基礎很薄弱,推薦兩個視頻課程供學習

· 牛課堂演算法精講直播講座(2017)

· 直通BAT:面試演算法精講課


追本溯源,理解場景。

比如我們講排序,你可能會想到快排/歸併/希爾等等,然而成熟的排序演算法,不會是單一的一種演算法。

比如我們講存儲,講索引,會說B樹,其實這個是配合機械磁碟特性來講的,多次查詢的效率遠低於一次查詢連續的數據,磁頭要來回移動,而SSD順序讀取和隨機讀取是一樣的,B樹其實沒有那麼有優勢了。

然而索引只有B樹么,hash也可以做索引,那麼相比B樹的缺陷是什麼,hash怕碰撞,要解決衝突,不能做索引排序等等一堆限制。

再比如hbase用的bloom filter演算法也是非常有趣的索引方式,在數據量巨大的場景下表現出色,佔用空間又少,當然也有對應的缺陷。

拋開筆試和刷題,理解這些演算法的設計和解決的問題,還是很有意思的。

所以我個人傾向於,先理解不同的演算法解決什麼問題,至少做到看到一個問題,知道要用什麼演算法來解決,再然後考慮提升演算法的實現能力。

--------------

有些答案基本沒法看了:

演算法是一種思想,沒必要綁死在C++/Java上。

推薦嚴蔚敏的書不知道什麼品位。

高質量代碼和精巧的演算法是正交的,沒必要相互貶低,

不是說會寫演算法,你的代碼能力就很牛逼了;也不是說工作中難以接觸演算法,所以學了沒用。

如果說找工作的話,我覺得操作系統和並發值得鑽研一下。


演算法是一個程序員的基本功。但是,為了找工作,沒必要研究的非常深入,點到為止。

目前研一,給身邊很多同學規划過研一安排,以針對明年實習招聘。竊以為,把本科數據結構那本書里的所有代碼都敲一遍,面大部分的互聯網公司都沒問題了。

為了以防萬一,需要深入一點,把動態規劃,背包,貪心,圖論,KMP,紅黑樹,並查集都過一遍;然後應該是沒什麼問題了。

推薦書《劍指Offer》,《演算法》(用Java實現的書,橙黃色)

推薦刷題地址: 牛客網,LeetCode, HDOJ


1,掌握基本演算法

2,遇到不會的演算法,能夠短時間查閱資料並掌握該演算法

總之就是保持學習能力,不僅是演算法而已。


首先回答第一個問題:學好演算法對一個程序員來說是必須的嗎?

學好演算法對於程序員來說是很有用的,因為演算法提供了一種解決問題的思維方式,而且作為編程學習的基礎,演算法知識的掌握可以加深對編程的理解。

學好演算法對於程序員面試來說是必須的,因為在程序員面試過程中有75%的題目都是與演算法和數據結構相關的,尤其是在國外的一些IT公司,演算法是面試中考察的重中之重,老外特別喜歡那些有ACM競賽經驗的面試者。

接下來回答第二個問題:至少應該學到哪種程度?

如果是平時學習的話,最好可以把所有演算法知識都過一遍,同時刷一下Lintcode上面的演算法題,在做題的過程中理解演算法。

如果是準備面試的話,一定要著重掌握以下演算法知識點包括:

二分搜索 Binary Search
分治 Divide Conquer
寬度優先搜索 Breadth First Search
深度優先搜索 Depth First Search
回溯法 Backtracking
雙指針 Two Pointers
動態規劃 Dynamic Programming
掃描線 Scan-line algorithm
快排 Quick Sort

這些內容都是面試中經常會考到的東西,在文章2017校招常考演算法題歸納典型題目匯總中你就能感受到考到的內容無非就是以上一些東西。

最後,演算法是需要好好學習的,學好演算法可以獲益終生。

歡迎關注我的微信公眾號:九章演算法(ninechapter),幫助你了解IT技術前沿,通過面試、拿到offer、找到好工作!


演算法作為知識是重要的,但實際應用編程很少需要自己設計開發演算法,所以對應用程序員來說,學演算法有用的方面是了解演算法的「常識」,在性能要求高的地方有評估、判斷和選擇的能力。


工作的頭10年用不到,往後看,如果沒學好的話也就到頭了。

學演算法,都不是學來就用的東西。簡單來說並不是門應用學科,到很重要,重要到了決定你在這個行業里能走多遠,我喜歡把這玩意稱為素質。

如果你只是照著書本上的例子應用,把演算法分什麼二分查找,最短路徑,二分圖匹配等等的應用範式,那麼很遺憾,在我的概念里你壓根沒入門。所以也根本體會不到演算法給你帶來的強大的力量。

那要怎麼學演算法?演算法是方法,是思想,是一種解決問題的思維方式。它教會你有序的問題可以使用順序所帶來的特性進行大範圍的篩選,時間和空間兩者是在一定的程度上可以互換的,等等的方式是在你人腦思維模式下根本沒有養成的思維習慣,而演算法是幫助你思考問題時更能夠發揮出計算機的優勢的思維方式的鍛煉手段。在之後的工作中也許你在也用不到形式上的演算法,但它已經融入到你行為的那個方面。


對於初期,學演算法可以練習手速,訓練編程思維,提高基本功。

對於工作,起碼演算法導論上的很少會直接用到,例如排序。實際中的排序會複雜的多,例如購物網站的商品示例 。但是這些對訓練你的思維很有效的。

同時,實際工作中的問題都是有解的,而且更多的是業務之間的邏輯。並不需要太強的演算法知識。

個人覺得演算法更多的是在設計上的對一些具體問題處理的技巧性,對於某個問題,高質量的演算法會顯得特別優雅。

對於後期職業成長這個我不敢說,我都還沒工作呢。但是實際上個人能發明一種寫入教科書的演算法是很難的,現在我們學的有些都是很久之前就證明的了 。去快拍排,哈夫曼編碼。

可以肯定的是,對你的代碼質量肯定有幫助。

最後,其實大量訓練的作用只是速度,真要都面臨一個都沒解決的全新的難題。還是拼智商


編程這條路沒有盡頭,請停止尋找這條路的盡頭。


其實學習演算法不一定非得是為了應用,更重要的是,演算法是思想的體現,他錘鍊你的思維,理解解決問題的理路。


其實演算法和工作需要,是個器與用的關係。只要人聰明會用各種方法去實現目標,基本演算法不會都行;如果人不聰明只會在眼前找解決方案,基本演算法寫得滾瓜爛熟都沒用,太多人說自己工作從來沒有用過演算法了。

笨的人只會去學演算法做鎚子訂釘子,學得多,也不過是多了幾個鎚子的工人;其實你就是沒有學過,找個封裝好的庫對於使用來說完全可以用。而聰明的人大腦就是變形金剛,想要鎚子還是改錐隨時自己搞定,會不會現成的鎚子無關緊要的。

至於我自己,反正是不聰明的,只好多學幾個鎚子啦


前天,剛通過清華XLAB孵化器的申請[呲牙],有點小高興,與大家分享一下。

那接下來,進入正題。

說演算法之道(第2版)中有這樣的一個記載,第一個飆車的人是德國首爾阿道夫·希特勒。

1943年春,在蘇聯刺骨寒冷,冰天雪地的環境折磨下,德國的戰爭優勢逐漸逆轉。德國首相希特勒為了排遣心中的焦慮,深更半夜起床,坐上自己的賓士吉普車,命令司機將油門踩到底,且不準放鬆。汽車在100多千米的時速下飛奔,零部件都嘎嘎作響。司機由於高度緊張而導致神經衰弱,換了一個又一個司機。但希特勒想要的就是兩個字:速度!只有這樣,他才能不斷享受飆車的快感!

其實,速度也是演算法所追求的。事實上,「速度」是演算法之魂。如果一個演算法在你的改進下,突然效率提高了成百上千倍,則當你坐在計算機前,看到的結果瞬間出現時所獲得的快感不亞於希特勒飆車體驗的快感!

演算法是程序之魂,一個程序要完成一個任務,其背後一定要涉及演算法的設計。實際上,只有學好了演算法,才能設計出更加有效的軟體。現在的計算機每年都在飛速增長,但是我們需要處理的信息量也是在呈指數增長。在科學研究方面,隨著研究手段的進步,數據量更是實現了大爆炸。無論是三維圖形、海量數據處理、機器學習、語音識別,都需要極大的計算量。在網路時代,越來越多的挑戰需要靠卓越的演算法來解決。所以說學習演算法是一個程序員必不可少的一門功課。

就拿我們剛畢業要參加工作而言,演算法是面試和筆試過程中不可缺少的考點。尤其像BAT這種大公司。對於怎樣才能學好演算法,要到怎樣的程度才能進入BAT。根據經驗而談,最基本的書籍莫過於《數據結構》,這是學習演算法入門的書籍。內容很詳細,主要的程序都有,可以按照文章內容把每道題編寫一遍。

若對演算法想更進一步了解的話,建議精讀一下演算法導論,此書涉及到數學推理多一點,有點難度,是進階的必備書籍。

至於練手的工具,我們可以刷一下leetcode或者各個高校的OJ。這樣在基礎演算法方面的入門,甚至演算法面試就沒有多大問題了.


找工作的話至少得懂基本的數據結構(鏈表 ,二叉樹,圖等),基本的內存關係(堆棧),然後是一些基本演算法(各種排序,查找,經典演算法問題(背包,NP等))。學數據結構學演算法的基礎是對指針理解到位……(? ??_??)?加油


現在你不大可能去發明一種新的演算法,也不可能在業務中照搬照抄一種演算法。但學了演算法可以讓你了解你常用的輪子的複雜度都是什麼,哪種情景下可以使用,哪種情景下就必須優化。演算法就是避免讓你寫出來那種「把停車場的車都撞一遍」的代碼。


既然是找工作,我覺得演算法這兩個字可以去掉。問題改成解決方案是不是必須的。

為什麼我要先改問題?因為演算法只是一種思路,但是具體問題我們要具體分析。所以就有了解決方案,在不同的條件制約和需求下,我們有各種優化過的思路。但是演算法只是一個頭腦風暴的遊戲。

那麼研究解決方案很重要嗎?重要而又不重要。

重要在於,實際開發就是不同的解決方案如同壘積木一樣組裝在一起。你不懂各個方案,你怎麼去開發?或者你只能做一個流水線上的開發人員,讓你具體負責一個組件開發或者性能改善,就瞎了眼了。

不重要的原因是IT發展了幾十年了,已經有各種各樣成熟的解決方案和思路。絕大部分時候,我們只要學會善用搜索工具,最終能找出結果或者自己總結出一個結果。比如之前對應了一個如何判斷光碟機是什麼類型等,我在硬體和驅動這一塊知識基本為零,但是有強大的msdn和谷歌,一樣解決了這個問題。

其次,語言發展了這麼多年,很多東西都已經有人幫你都做好了。比如上面有些人說的什麼基本演算法,排序查找等等。說實話,其實你不知道都沒有關係。比如java,你要從一個數組裡面找東西,要知道什麼演算法?index一句話解決。排序,用冒泡還是快速?不用,一個比較器就搞定了。很多需求,隨著開發的不斷深入,很多新的語言都事先給你都做好了。前期追求不高,你會用就可以。而隨著你開發的經驗上去,自然而然會有很大成長。

最後,在工作中,一些特別巧妙的演算法其實我個人並不推薦。很多演算法提升了3倍5倍的性能,但是實際上並沒有大量的數據和處理前提下,提升的性能對於現在的硬體來說,沒有任何效果。但是反過來,很多程序員並不擅長表達,所以寫得東西注釋沒有或者亂七八糟,很容易導致後期維護難度的大幅提高。

高質量代碼重要因素,可讀性,可變性,可維護性。

所以,在做到以上三點的前提下,再增加自己的解決方案的豐富經驗。程序員最值錢的地方之一就是經驗。


你覺得需要就需要,如果你覺得不需要,那就不需要。

就這麼簡單。


首先

程序員的作用是實現需求和解決問題, 演算法不是這條路上的必須手段, 但是你不會是萬萬不可以的(看不懂別人的解決方案 / 沒有優化思路 / ...).

所以, 演算法要懂, 但是不用特別深入, 至少你在腦海中有個index(不熟演算法,你可以查可以練, 千萬不能不知道). 解決方案嘛, 上面有人說了..看書, 刷題...

然後Android我覺得本質上就是個前端....所有都是在實現client, 你不懂演算法一樣也能折騰app, 但是懂了演算法和數據結構你在拆解源碼的時候能更深入的理解別人在做什麼以及這個系統為什麼這麼做, 長遠來看這個能力對提高自己有事半功倍的效果, 是你天賦樹上的關鍵一個技能點..你可以不點高, 但是你不能不點.

綜合一下, 無論你走不走Android道路, 演算法和數據結構都是繞不過去的, 並且這是一個長期的修鍊過程, 一開始到應付面試的程度, 然後再看情況繼續深入吧.


最近在寫動畫 搞了兩天沒搞出來


正面回答樓主的問題:

1.必須的,因為演算法不精通面試過不去。

2.程度,通用演算法必須學會動歸思想,數據結構至少熟練到兩分鐘手寫紅黑樹(沒人管你是不是背的)。專用演算法,比如A*,JPEG之類的看行業,所舉例的兩個就不會出現在同一個面試中(出現了你打我啊:-D)

題外話,

1. 實際工作中用到的演算法跟行業有很大關係,一般的語言庫,開發包,kit裡面都封裝必要演算法,以普通應屆生水平很難優化的超過庫本身水平。

2. 確實需要用了的時候百度既可。


推薦閱讀:

android開發是否被h5代替?
Android Design 與 iOS 人機界面設計的區別是什麼?
打開google play閃退,並且顯示「Google Play 商店 已停止」,怎麼辦?
為什麼有很多用安卓的人對蘋果用戶有種莫名的優越感?
MIUI 是否會被其他各廠商同質化?

TAG:程序員 | 演算法 | 編程 | Android開發 | Android |