怎麼看待程序員普遍缺乏數據結構和演算法的知識?

幾點說明
1.題主不在一線城市,公司面試要求數據結構和演算法
2.所問的問題都很基礎,類似於「數組和鏈表元素在內存中存放特點?,查詢第n個節點時間複雜度?」,「二叉樹遍歷」等,候選人答對比例差不多不到兩成,工齡越長,比例越低。
3.如果不問這些,問哪些(.net方向)?


學校沒教過,工作中用不到,時間長了也一直不會;
學校沒教過,工作中用得到,時間長了也就會了;
學校教過,工作中用不到,時間長了就忘了;
學校教過,工作中用得到,時間長更熟練了;
=========================================
N年經驗還從事開發工作不會這些東西且混的還可以的,說明他的工作中不需要這些東西,尤其是做MIS的、圍著資料庫轉的。
=========================================
程序員鄙視鏈:
科班出身的&>非科班出身的
純IT公司的&>行業IT部門的
純做技術的&>技術+業務的(做行業的)
數學好的&>數學差的
。。。


暫且不討論實際開發中用不用得上。

就重要性來說,這些演算法也不是最重要的。I/O是最大的瓶頸,演算法的優化是渣渣。你用了樹,頂多把線性階給優化到對數階,但是你一個不注意,把本該放到緩存中的東西寫了本地,就可以抵消掉所有演算法方面的優化。

而複雜度方面,只要一個普通的程序員,再怎麼搞不清楚鏈表和數組,也很少會寫出立方階甚至指數階的實現來。

而且我認為,樹、圖、鏈表的實現是狹義的演算法。廣義上的演算法是複雜度分析,就是看出你項目中每個模塊的複雜度,挑選符合要求的來用,從而避免寫出來性能過低的東西。


// 華麗的補充回答

被輪子哥翻牌之後多了好多贊,受寵若驚。

有不少知友們在評論里表達了 「做系統開發的並不需要對底層的基礎演算法了屬於心」 的觀點。我是可以理解的,畢竟用java也不需要記得排序的具體演算法,直接Collection.sort()就解決了。

但是,大家可以注意下題主問的第一條是 「公司面試要求數據結構和演算法」,既然要求寫在這了,我的假設就是工作上有這樣的需求呀…

" 不如之前華麗的分割線

我覺得和很多人學程序不打牢基礎有關。

你在網上隨便看看就能發現很多類似於 「想學java/python/c++/… 請問應該怎麼入門」 的問題

底下的回復大部分都是告訴你看哪幾本書,把String,IO等基礎的語法弄明白,有點基礎了就直接根據你是想做手機app開發還是web開發再選擇不同的路繼續走下去…

我們再回過頭看看一般學校里是怎麼教。

別的學校我不清楚,就我上的大學來說,語言是次要的,一開始打基礎教的是數據結構:
比如說線性的array, ArrayList/Vector, Stack, Queue, Hashmap, ...
然後是非線性的BinaryHeap/PriorityQueue, AVL tree, UFDS, ...

演算法也是從各類排序(bubble sort, quick sort, radix sort, ...)教到各類和圖論有關的(BFS, DFS, Kruskal, Dijkstra, DP, ...)

這些基礎課都上掉,大家再去選方向,想搞AI的搞AI,研究DB的研究DB,喜歡遊戲的做遊戲開發…

學校都沒有幾門專門的web編程課,為什麼呢?

我覺得web編程也好,手機app也罷,都是應用層面,遵循固定的教程就能開發出來,如果不深入底層,都不需要怎麼思考的,純靠多做有經驗了就能找到工作。

殊不知演算法和數據結構(也就是數學有關的東西)才是關鍵呀!

# 華麗的分割線

答主說感覺經驗越豐富的程序員演算法和數據結構的基礎越不牢靠,我認為和程序員們在真實工作中不斷被告知 「Don"t reinvent the wheel." 有關。

前段時間互聯網熱潮,各種創業公司如雨後春筍一般冒出來。而創業公司需要快速更新自己的軟體,儘可能的把有限的時間用在開發核心項目上。
所以除了專門做底層開發的人員之外,大部分做app和web前端的程序猿們能在網上找到答案的話就不會自己寫,於是產生了大量的 cv(ctrl+c / ctrl+v)程序員,面向Google / Stackoverflow編程的程序員們。

雖然不論黑程序員還是白程序員,解決了問題就好程序員。但是往往我們在根據別人經驗解決了問題之後並沒有去思考為什麼,久而久之除了提升了搜索技巧外,自身的編程基礎反而有所下降。

這也是為什麼我上知乎看到了輪子哥@vczh的個人描述之後果斷關注了他(才不像你們那麼污 XD)。

希望廣大程序員們在解決問題的同時多問幾個為什麼,沒事也造造輪子。

共勉~


讓我想起一次去一家小公司面試的時候,面試官給的編程題是不使用系統庫自己實現一個字元串查找的函數。

然後寫完了之後,面試官翻過來翻過去看了半天,然後問:
「這個是……KMP?」
「是啊。」
「哦,獵頭是不是給你透題了啊……」(我是獵頭電話約的)
「沒有啊,絕對沒有。」
「哎呀,我知道他們有時候會提前透露一下面試內容的。」(言下之意:哪有能現場寫出KMP的人啊)

我當時心裡一肚子火,你TM就沒覺得對方能答出來你還問,答出來了你還覺得是作弊,你質疑我技術水平也就罷了你還懷疑我人品,你倒是見過拿Python寫KMP的嗎……

我的確不記得具體演算法的流程,但我記得演算法思路,KMP實質上是一種動態規劃,所以按照原來的思路重新設計了一遍這個演算法,還在草稿紙上畫了草圖。

有的人問演算法是因為工作的確需要,有的人問演算法是因為自己也不專業,不知道該問啥,問書上寫的肯定不會錯。既然問的人會覺得答不上來也是理所應當的,那他們自己也自然不會去補習這些知識,問演算法、數據結構就變成不專業的程序員和不專業的程序員之間的例行公事了。


「數組和鏈表元素在內存中存放特點?,查詢第n個節點時間複雜度?」,「二叉樹遍歷」,這種問題是最基本的問題,只要是做技術的就是快退休了也應該知道。
  要知道,工齡長並非可以不知道這些的借口,作為一個工科生在畢業以後先做冰糕再做汽車又轉行從政數十年了之後,還能一邊旁徵博引「一尺之錘日取其半萬世不竭」,一邊在黑板上給大學生講高等數學呢。——而你不過是一個工作了幾年的程序員,就有借口說自己不知道鏈表和數組的區別了?不會寫二分查找了?不會遍歷二叉樹了???
  當然不少計算機專業的學生在數據結構考試之後的第一個寒假/暑假就已經把這些忘乾淨了,如果到畢業的時候還沒有忘記,工作很多年也不會忘記。考這種題目的意義不在於工作當中會用到,而在於證明候選人有基本的演算法能力,編程也要遵守基本法,這種基本的演算法能力就是基本法,你說能做出來是不是最吼的?
  因為程序員不僅僅是調用API就完事兒了,還需要在已有的API基礎上加上業務相關或者需求相關的邏輯,這時候是不可能找到現成的代碼或者第三方庫的。比如做一個客戶端採集數據然後上傳伺服器,並且在客戶端顯示的功能,按說只要調用服務端http請求,響應採集來的數據就可以了,並不需要什麼演算法啊數據結構的知識,也是很常見的應用場景。但是採集來的數據和伺服器端數據如果不匹配,要做數據格式轉換的話,數據結構設計的不好轉換起來就事倍功半,演算法基礎不好轉換代碼就很難維護而且效率低。一般來說最初設計採集到的數據和伺服器端數據格式一定是一樣的,但是隨著時間推移需求變化,一定會出現不一樣的情況,這時候沒有基本的演算法能力做出來的程序是沒辦法適應第二個版本的。
  這種場景是很常見的,比如現在很火的智能手錶/手環,就需要採集心率、計步上傳伺服器。
  項目經驗、當紅應用的開發經驗當然重要,但是沒有基本的演算法能力就只能做搬磚工,根據別人的指導來開發項目,只有具備這方面能力才能成為一個項目的核心人員,哪怕只是一個小項目。最好的考察方式我以為應該是在實際應用當中抽取場景讓候選人來完成,退而求其次是考察基本的演算法和數據結構。實際場景最貼合實際也最實用,但是一般不太容易抽象,或者涉及到業務邏輯不好理解,所以有時候考察基本的演算法和數據結構也是不錯的辦法,可是存在可能候選人有可能在網上查查做出來或者抄下來,這是一個大缺陷,要麼結合一些實際應用中的題目,另外就要面試的時候再把一道關了。

補充說明:
如果是需要在網上查了才能寫出來二叉樹遍歷,那不算掌握基本的演算法能力,是典型的google程序員或者百度程序員。能在「默寫不出」的情況下根據二叉樹定義自己寫出來二叉樹遍歷,才是掌握了基本的演算法能力。
因為公司開發的應用裡面有很多要根據用戶場景(類比二叉樹定義)來實現業務需求(類比二叉樹遍歷)的地方,這些不可能在網上查出來,要麼根據別人給出的演算法或者流程來實現,要麼自己研究需求總結出來流程或者演算法。做前者就是一個普通的搬磚程序員,工作也能找到但是薪水不高也不太累,但是沒有什麼成長空間,會優先被裁員;做後者就可以邁向核心程序員之路,工作好找,薪水會高點,會比較累或者很累,一般在公司第二天就倒閉的情況下才被裁員,成長空間是就任CTO迎娶白富美——當然只是一種可能,不過前者連這個可能也沒有


答主也算是一個有點經歷的程序員,在獵豹移動、百度、創業公司、騰訊,都呆過,也多多少少接觸過一些程序員,題主說的問題,在我看來就是區分科班出身的程序員和非科班出身的程序員最簡單的辦法。
對於科班出身的程序員,特別是211以上學校的根正苗紅的畢業生,別說是來面試程序員的,就算是來面試產品經理的,基本都能答上來,畢竟題主問的東西實在是太基礎了!
//////////////////////////////////////////////
其實我覺得答得出,答不出其實都還好,關鍵是看他們對待未知知識的態度,如果是像幾位大V的高票答案那樣……
「不是我錯了!是這個世界錯了!」
well……


你們噴了這麼多,難道不看看題主問的到底是啥嗎?

如果不問這些,問哪些(.net方向)

招.NET開發的話,我是不是可以默認是招寫業務代碼的?
請問,一個寫業務代碼的需要知道多少關於演算法的東西?
只要會算時間複雜度,知道不能上N的多少次方的演算法就差不多了吧。
哪怕真遇到了性能問題,
在理清業務邏輯的基礎上,
1.減少IO操作,
2.合併剪除邏輯分支,
永遠是最優先考慮的方法。

別說反轉二叉樹,估計工作幾年二叉樹都碰不上一個。

需要去動演算法的腦筋,基本是別的地方已經擠不出水了,但是這種情況,對於一般的公司來說太少了,講真,你遇到這種情況,加幾台伺服器比雇個能在這個層面上解決問題的工程師便宜不要太多。
問數據結構和演算法,我覺得Leetcode上拖幾個easy,能證明他是程序員就行了。

但是,面向對象的基本原則,設計模式的經典場景是不能少的。
不然你就等著在review的時候驚嘆「這tm怎麼能這麼寫」,
在用戶改需求的時候頭疼「這tm是誰實現的」吧
性能不行還可以加伺服器,代碼腐化了,那就只能推倒重來啦。


我很可能答不出或者答錯這類問題,但是幸運的是,不可能再有人用這類問題來面試我了。

面試我的時候賓主雙方會在親切友好的氣氛中就未來技術發展趨勢中幾個共同關心的問題彼此充分交換意見達成共識。

在實際工程實踐中,高速緩存,SIMD指令和某些內存訪問特性會顛覆你從書本上學到的關於演算法數據結構的時間複雜度的認知。

O(n)不一定就比O(logn)慢,順序搜索數組不一定比二叉樹查找慢。
內存,網路和外部存儲的IO性能對演算法和數據結構的選擇起決定作用,cpu速度不一定是最大影響因素。


我想,唯有國家出台法律強制規定:
懂數據結構和演算法的程序員工資翻倍,
才該能在短時間內解決這個問題。

並:
進行嚴格的年度考核。
才能保證其長效機制的作用。

否則,無解。
不信可參考:考研馬列科目
——最終都還是忘了。


我認為答不出來很正常啊。像二叉樹翻轉這麼難的題目,連Homebrew的作者都答不上來。你指望我能答上來?

知識是無窮無盡的。不知道就不知道了,這不可恥。我就不信你答的出李阿玲出的五個問題。我認為知識掌握的多少根本不重要。因為無論你知道的再多,你總是會碰到之前沒碰到過的問題。寫程序時,真正浪費時間的就是你不知道的東西,而不是你知道的東西不熟練。你實際開發過程中,真的需要反反覆複寫500遍紅黑樹么?

做程序最重要的不就是要面對未知么?
—— 在真實工作中的編程是怎麼樣的,與學校里有什麼不同? - 李阿玲的回答

更可笑的是,據不完全統計,87.53%的考察知識點的面試題標準答案都是有問題的。很多人出題就喜歡自己剛學了什麼覺得很新鮮就當題目出了。往往導致就是不知道就完全答不上來,真的用過又會覺得這個題很不合理或者在實際使用中應該盡量避免的(請自行腦補 (*++a)=a++++++a)。

依我看這些破玩意兒就是21世紀的八股文。


1,老程序員沒法一下子寫正確快排我覺得沒問題,但是說不出快排的思路,我覺得問題很大;
2,老程序員不知道某一特定語言鏈表和其他語言鏈表的實現細節區別我認為沒問題,但是不知道基本鏈表/二叉樹/哈希表的時間複雜度,我覺得問題很大;

這些其實不是細節,但凡寫代碼尤其業務相關,必然要考慮這些


以前演算法+數據結構=程序,是因為程序往往是用來解決數學問題的。
現在程序的概念已經變成工程了,如何設計眾多組件把資源組合在一起實現目標才是最重要的,演算法只是其中的一個環節,而且有一大堆的庫幫你封裝。
就像照明,以前要拾柴禾,打燧石,扇風,才能有火光,還要不斷的添柴禾以免火熄滅了。現在只要按下開關即可,重點已經不在如何點火上了,而是燈要擺在哪,亮度如何,要放多少個。知道led發光原理甚至如何製造led燈有助於你的照明效果,但大多數情況下不需要你這麼費事,你只需要去買一個造好的湊合用就好了。

工齡長是因為轉向管理已經不care這些了。
比如你問校長泰勒展開怎麼證明,你覺得校長會嗎?


其實根本事社會分工變化, 早期程序員受限於機器限制和上機時間的限制, 所以在軟體裡面會做到極致。而現在機器越來越強大了, 手機馬上都要開始4G內存8核CPU了,所以程序員這個行業出現了分工, 有人做這早期程序員的工作開發系統級工具供大家使用, 而出現了一個新職業運維, 他們負責調試這些程序的參數。緊接著程序員更加細化了, 出現了web,pc/mac, 安卓, ios程序員, 後端程序員。然後這些程序員對於雖然直接使用了一些系統工具,但是對底層理解比較透徹。在大環境下面由於需要相當數量的這樣的程序員, 那麼現在以次充好就出現了各種API程序員, JS 程序員, css程序員, html程序員。

說到底程序員需不需要數據結構, 對於程序員來說是需要的。但是工作不一定需要, 很多人也就謀求一份工作而已。


瀉藥。

是我。後悔基礎當初沒學紮實。(認真臉)
一點點把之前沒學好的慢慢補回來。成長的過程總是痛苦的,刷題的時候覺得自己各方面被碾壓,挫敗感很強。覺得自己智商感人,不配當一個程序媛。
恩,我還年輕,要好好努力,未來還有很多可能。
摺疊我吧。


答不上來這些就是個不合格的程序員。

「數組和鏈表元素在內存中存放特點?,查詢第n個節點時間複雜度?」
「二叉樹遍歷」

這些基本上屬於常識性的東西,應該已經內化了。答不上來有點過分。倘若你要問的是什麼紅黑樹的刪除操作啦,手寫 kmp 演算法啦這種問題,答不上來實屬正常。畢竟很多細節性的東西如果不常用記不住也情有可原。

你別看高票的幾個大神吐槽的歡,你要是問他們「數組和鏈表元素在內存中存放特點」肯定都答的上來。「非遞歸反轉二叉樹」就不一定了(話說 Max Howell 就因為這個被 Google 給拒了2333)。

怎麼看待這個問題呢?程序員也是分好幾類的。有搬磚的、工程師、架構師 balabala 的。看你要招哪一類的人了。有的工作確實不需要知道些很細節的數據結構的東西。我就見過需求文檔裡邊連偽代碼都差不多給好了,直接翻譯的活 Orz。你要是要招這種人,也就無所謂啦。沒必要感到氣憤或者遺憾什麼的。你看 Jeff Atwood 在他博客裡邊都吐槽要面試者寫個求100內素數的函數,多一半人的寫不出來,中外都一樣的。方便起見最好在招人的時候讓他們在 OJ 系統上做兩道 Hello World 級別的題目,互相之間節省下時間。之後再面試會好很多。


這個問題很簡單
我們為什麼要高考?高考完之後原來學的知識大部分都用不上了,那換言之也就是高考的制度是失敗的。
但其實不然。通過高考篩選出來的,是聰明的人和努力的人。

所以,即便在今後的工作中根本用不到數據結構和演算法,但是對這個的掌握是最基本的,如果真的8成都答不出來,那說明它真的達到了篩選的作用。一個連基礎知識都掌握不牢的人,在用人單位沒有理由在完全不了解他的情況下信任他的工組能力以及作為程序員的自我修養。


用基本的數據結構考察邏輯能力,誤判率低


我認為學習數據結構與演算法的目的主要是在忘記了數據結構與演算法之後,我們還記得的那些東西是十分寶貴的,比如現在讓我寫一個快速排序,我可能一下子真的寫不出來,但是我至少還是知道快速排序的思想是利用分治和遞歸的,而遞歸和分治又是一對好基友,而實現遞歸呢,又不能無限制的永遠實現下去,必須得有終止條件,而與遞歸相關的二叉樹的遍歷還算比較簡單,三種遍歷方式除了輸出語句的位置不一樣幾乎沒啥區別~
所以,數據結構與演算法的重要性在於,我可能暫時用不到,但是一旦我需要的時候,我至少必須想到和什麼有關,這樣才能順著線索去找你需要的演算法~


大v說的就是對的?哎。
數據結構本來很重要的知識,退一萬步也是一種好的思想。用不到就不用學了,演算法不是瓶頸就不用學了,還上這7年大學幹什麼。科班的知識只有用到工程領域才算是必要嗎?恐怕不是吧。有些東西叫做潛移默化,就像軟體工程這種課程,你不去學習,也不會妨礙你編程,但是你如果掌握了,會讓整個工程的開發,代碼的管理維護更加規範。你開發了這麼多年一直沒用上,請不要說他就沒用。
專業知識的產生並不是無緣無故的,不依賴大v意識而獨立存在。


我工齡12年,面試也不會有人傻到問我:你知道二叉樹怎麼寫嗎。。。。。


推薦閱讀:

面試提問2的10次方是多少是否合適?
一般在寫SQL時需要注意哪些問題,可以提高查詢的效率?
當面試官說「你之前做的項目沒有什麼難度」,應聘者應如何應對?
面試題:如果直屬上級給你 100 元假鈔,讓你儘快買一杯咖啡,你該怎麼辦?
阿里 HR 坑人事件真相是什麼?

TAG:程序員 | 面試問題 | 演算法與數據結構 | 程序員招聘 | NET程序員 |