編程能力主要是演算法嗎?

首先演算法很重要這是毋庸置疑的。但是我的疑問是,現在好多程序設計比賽或是編程能力測試主要的都是考得不同難度的演算法,所以編程能力等於演算法能力么?


問題相關:本科玩過ACM競賽,畢業之後做了開發,見過很厲害的開發也見過很厲害的演算法,算是有一點點眼界,厚著臉皮來達下這個問題。

以下回答純屬個人理解,不喜勿噴,說答主是菜雞也沒關係。

我講下我自己的故事吧,我盡量說生動一點,希望能夠幫到你。

我從大一開始就一直玩ACM,由於分心比較多,訓練也不算最刻苦的,所以在學校里實力也就還行。因為一直沒放棄,多少有點積累,也算是拿了一點小獎。

憑著曾經ACM拿過的獎和一點點的運氣,在15年的時候拿到了阿里演算法崗的實習。直到我拿到實習offer之後,我才發現,原來演算法崗的實習要求和我理解的會的並不一樣。做過的人都知道,ACM比賽涉及到的其實是性能演算法。在規定的時限和空間內計算出要求的結果。並且這個結果是固定的。

而現在市面上大多數的演算法崗位,所涉及到的都是智能演算法。也即是所謂的大數據演算法,這個詞逼格比較高,所以大家都愛用。這類演算法的特點呢,是基於海量的數據進行統計或者預測。就我個人的理解而言,更偏向於統計。這類問題一般來說沒有最優解,只有近似解,通過優化模型和方法,可以獲得更好的效果。

以上這些是我進了阿里之後,發現自己什麼也不會慢慢學習領悟到的。在我實習期間我做的事情,基本上都基於阿里的odps大數據平台。利用平台本身的高並行性計算能力,對於淘系內海量的數據進行篩選和處理。說得low一點,其實就是寫類SQL語句,嵌套Python寫的機器學習演算法腳本進行數據處理。最後根據結果,修正參數,達到更好的效果。

原本我感覺實習期間的表現都還不錯,雖然機器學習方面的領悟還不夠,但是自己學得還是挺快的,而且搞過ACM,腦子好使,以後慢慢總能上道的。然而,不知道是我運氣好還是運氣差,我遇到了十年一遇的「擁抱變化」。我成了兩千多人中另尋下家的實習生中的一員,為了不至於餓死,在我投簡歷的時候我遇到了一個問題。

究竟是做開發還是做演算法?

比較逗的是,當時自己心智還不全,這種二選一的問題實在是糾結。在阿里待得久了,寫完SQL跑很久的日子真的是有些倦了。感覺對這樣的日子不太喜歡,太浪費時間。但是機器學習也學了,而且說實話開發那些除了Java會一點之外幾乎一竅不通。最後猶豫了很久,決定兩者都試一下,拿到哪個offer就干哪個。當時覺得自己實在是太機智了。

開發我投的是現在的公司,演算法崗是當時的HRG內推的創業公司。(我當時的HRG還是挺好的,阿里的hr也不像知乎里說得這麼誇張。雖然我不記得她的花名了,不過還是很感謝她當時願意幫我

然而,不幸的是,這兩家我都拿到了offer……

經過了仔細思量和權衡,最終選擇了蘑菇街,具體的心路歷程在我的另一篇答案里有寫。蘑菇街,網易,阿里校招offer選擇? - 小狼MOUT 的回答 - 知乎

其實還是有點小後悔,自己本科搞了四年的演算法說放棄就放棄了,選了一條之前不太喜歡也不太擅長的路。

在我實習的時候,這種情緒來得尤為厲害。為什麼呢?因為感覺做的事情和我預期的完全不一樣。身邊的都是一群不懂演算法的人,寫的也是之前不太喜歡的Java語言。我不知道怎麼樣形容,也不是說覺得同事low,只是有一點點落空。

特別是當時帶我的師兄打開了debugger,單步跟蹤查錯的時候。我用詫異的眼神看了他一眼,因為在ACM玩家眼裡,debug應該都是用肉眼完成的。之前因為受到一些學長的引導,覺得開發要簡單很多,應該很快就能勝任,加上acmer的手速都比較快,所以當時的心態是比較激進的。

當然,沒過多久,我也用上了debugger。開發和演算法不同,程序崩潰的原因實在是太多了,代碼有問題只是其中很小的一部分。很多錯不用debug根本無法排查。

然而當我畢業完了之後再次回到公司,現實立刻給了我一個下馬威。師兄太忙了,被調去了其他事情,之前巨大的項目丟給了我。我不僅要負責所有的需求,並且所有的問題也要一併承擔,從排查到修復,只能我一個人搞定。

SSM框架、公司的各種框架、網路架構、tomcat、maven這些我都幾乎一無所知,甚至連git也不是那麼熟練,更別說JVM那些比較高端的了。我感覺我之前搞ACM積累下來的代碼能力完全成了空白,當時一度是比較低落甚至是有些悲觀的。

然後呢,然後我是怎麼克制的呢?

不得不說,我遇到了一個很好的leader。他會給我們分享很多很多的技能,從他擅長的排查故障到JVM、多線程和一些框架等等。他分享完會讓我們做些總結,我比較聽話,每次都會總結。

到了這個時候,我才發現,其實開發要學的東西並不比演算法少。原本這就是兩個領域,架構、設計模式、面向容器或者是環境的調優等等,深挖起來可以挖的東西實在是太多。很多技術實力很深的人並不懂什麼演算法,甚至連排序都寫不出來,但這並不意味著可以否定他的編程技能。

舉個簡單的例子,這例子是我主管跟我講的。比如同一個需求,他實現和我實現同樣都是實現。然後會有什麼不同呢?我來實現,雖然都實現了,但是所有的東西都是寫死的。以後有類似的需求進來,還需要另外搞一套。如果是他寫,雖然花的時間差不多,但是就會做成可配置的,以後只需要改改配置,就能在其他的地方復用。這些還只是一個方面,還有穩定性、代碼復用率等等講究。

言歸正傳,繼續講故事。當時受到主管的影響吧,自己遇到問題的時候也會多思考,這種問題出現的原因是什麼,解決的原理和方法是什麼,而不是簡單地把問題幹掉。其實開發的套路相對比較固定,問題的種類也就大概那麼一些。多踩個幾次坑,也就慢慢有經驗了。

在我努力學習技術的這段時間我發現了一個事情,就是同樣的東西我理解起來總要比別人快上一些。就比如我們公司無線端框架的源碼,沒有人給我講過裡面的構造,就通過文檔和啃代碼,我能理出其中的設計模式。再比如業務需要用到狀態機,我大概在網上看個概念,就結合自己的業務進行實現。

不僅僅是後端這些,在我學前端ES和react甚至iOS開發的時候,也經常會有這種感覺。就有一種這東西原理好像在哪裡見過,一點就透的感覺。

為了這件事情我還奇怪了很久,直到後來和朋友的一次談話提醒了我。有過一個演算法崗的朋友,機器學習很牛的人。一直聲稱自己不會寫代碼,以前我完全不信,能把機器學習玩這麼溜跟我說不會寫代碼?不是搞笑么?

直到後來我自己學了機器學習之後有一次幫一個線上獵頭公司面了幾個演算法崗的實習生,看著他們簡歷里少得可憐的開發項目,以及隨便問幾個簡單的思維問題都想不出一個很好的答案。不就像我當時實習的時候,面對一大堆開發問題一籌莫展的樣子么?

恍然大悟,原來朋友所言非虛。這才發現之前陷入了一個誤區,之前一直有一招先吃遍天的想法,認為演算法厲害到一定程度,編程肯定也厲害。

那時才一下子明白過來:演算法能力從來就不等於編程能力,編程能力是一個比較空泛的概念,裡面涵蓋的東西太多,和方方面面都有交集。甚至有些研究統計和數學的教授雖然不懂代碼也可以看做是半個程序猿,畢竟他們對程序需要的邏輯和所需的技能掌握到了非常高深的地步。翻下語法書就能上手寫代碼,你能說他們沒有編程能力么?

所以問題編程能力的主要是不是演算法本身就是一個偽命題,單單什麼是編程能力就可以說上半天,都不一定有人能夠說得清楚。而且一個集合大到了一定程度,很難分清到底什麼是主什麼是次。

那麼你可能又要問了,為什麼演算法不是編程能力的主要部分,各個公司還那麼看重呢?

這個問題就要簡單很多了,原因也比較多。

首先,開發能力不是很好衡量。單單從面試問幾個問題,或者看一看你做過的項目並不能很快並且精準地衡量出一個人的開發水平。我可能之前在的項目組接的項目比較水,但是我的架構寫得特別清晰,代碼質量很高。但是你只看簡歷說不定就會覺得這個項目沒啥技術含量。但是演算法就不同了,一些複雜的演算法理解起來就很有難度。你能理解並且掌握,本身就已經說明了實力。更不用說ACM之類的演算法還能拿來比賽,你什麼實力,和其他人比一比就知道了。(微軟、谷歌等公司都是這麼乾的,而且都有自己舉辦的比賽)

其次,雖然不能說演算法是編程能力的主體,但是它真的對人鍛煉作用比較大。有點像是武俠小說里的內功,同樣的三年時間,你學三年劍法就可以當街殺人。我練三年內功啥也不是,但是,假如再給三年時間,我們再練三年,結果說不定就完全不一樣了。例子可能不是特別恰當,但是大概這麼個意思。

一些演算法對於解決業務和架構問題非常有借鑒意義,學過演算法的人上手什麼的都要比沒有學過的人快很多,這也就是為什麼我感覺當時學那些都比較快。

對於企業來說,演算法比較容易通過比賽等途徑衡量,並且也客觀反映了一個人在編程上的潛力。而且做過ACM的人一般都在程序的性能上比較有追求,比如儘可能地減少內存開銷降低複雜度等等。像是谷歌這樣的公司將演算法當做敲門磚,可能也有看重這些的原因吧。


不完全,但是如果你信了那些演算法不重要的言論就遲早要完。這幾年互聯網很火,搞得好像會點軟體都能賺大錢,一幫人用的都是別人做的東西,只是拿過來拼湊下就能用,並不是說這樣不好,畢竟這幾年互聯網還火,但過幾年呢?互聯網不火了呢?新興產業出來了呢?那些靠拼湊過日子的還能拿到現在這麼高的工資嗎?

之前電子行業火的時候好像誰都能賺到錢,現在除了幾個大公司還有幾個能有當年的得意樣?


編程是一個世界,演算法是這個世界的高山大河。但世界不只高山大河,有不起眼的平地,不壯觀的村子,交錯的道路,立體無限的空間。

演算法不只是哪種排序方式大O最好,還是當下哪個方法更合適。演算法不只是課本上的那些經典,更是正在發生的沒寫進課本的,解決生產問題的那些。

編程等於數據結構加演算法是學校老師愛說的,他們要簡化教學模型。

但你自己要學會擁抱世界的混亂,這才是程序員真正面對的。


不。編程是一個系統的工程,其中包含非常多種方面的能力。而對於編程所要解決的不同類型的任務而言,所需要的能力的側重點也完全不一樣。如果要列舉一下的話,我認為至少有如下。

  1. 編程的思想。也就是計算機解決問題的基本思路和模式,比如對於各種選擇,循環,遞歸控制過程的掌握。通常來說在人們學習第一門編程語言的時候實際上就是在學習這方面的技能。可以說面向過程,面向對象,函數式編程等也是這個類別裡面。
  2. 對於編程語言的語法,規範,最佳實踐等的掌握。對於已經有1的基礎的,學習一點點基礎的語法即可很快的對另一門新的語言上手,這也是很多人說學習一門新的語言很簡單的原因。但是需要知道,每一門編程語言都有自己的細微的特點,要達到充分的掌握並非常熟練的使用,還是需要花費很多的功夫來學習的。
  3. 能夠對於要解決的特定的問題選擇更好的時間和空間開銷的解決方案的能力。通常來說也就是數據結構與演算法的能力。雖然演算法可能是一個非常宏大的概念(任何用計算機編程解決問題的方法你都可以叫做演算法),但是這裡我們可能主要側重於對於一個問題的時間和空間複雜度的分析和優化。
  4. 對於標準庫,系統API,以及第三方類庫的了解和熟練的使用。需要能夠知道這些庫的具體邏輯,能夠有能力快速的在文檔中查找到自己需要使用的合適的API,或者選擇使用合適的庫。
  5. 能夠合理的組織代碼,達到易讀,易擴展,易於變更等。能夠對軟體項目的開發過程當中的各種方面進行合理的組織和管理。通常就是設計模式和軟體工程。
  6. 能夠對計算機系統本身有足夠的了解,對編程過程中直接或者間接使用的工具有足夠的了解。通常說來著意味著對於計算機組成,操作系統,編譯原理,網路原理等計算機系統基礎的深入學習。雖然計算機體系的設計都儘力的把下層封裝成一個黑箱,使得上層可以不用考慮黑箱中的細節。但是這種封裝其實不可能完全隔絕這種差異。很多時候你都需要對更底層的東西有更好的了解來幫助你設計上層的系統。這對於性能的提升和問題的排查實際上都有著很積極的作用。
  7. 對於要解決的問題相關的特定領域的知識。對於不同種類平台的應用開發,計算機科學裡面的各個子領域如人工智慧,圖形學等。這涉及到你如何能夠應用編程的能力來解決實際的問題。
  8. 能夠熟練的使用一台計算機,包括但不限於熟練的安裝各種軟體,解決系統問題,配置奇奇怪怪的開發環境。
  9. 有足夠好的英文閱讀能力,有足夠強的自學能力,有足夠強的在互聯網上有效的檢索信息的能力。
  10. 有進行抽象的複雜邏輯思維的能力。

對於任何真實世界中的問題而言,都必然是一種系統的工程。這都涉及到綜合運用你擁有的能力和資源,對其進行合理的優化配置,對於要完成的目標進行必要的取捨。對於每一種不同的具體任務而言,對於以上每一種能力的要求都是不一樣的。簡單化的描述編程能力主要應該是什麼,都是不恰當的說法。


與其說是演算法,不如說是抽象能力加演算法


不是,只是演算法之外的能力很難進行標準化考核,所以很多時候只能考演算法。


編程:搭積木

基礎編程能力:能把積木按照圖紙搭得又快又好

高級編程能力:熟悉每個積木快的性能(即熟悉基本的數據結構和基本的演算法 ----- 熟悉,表示「知道怎麼回事但不需要能親自用代碼寫出來,能用偽代碼描述清楚即可」)、能設計出最符合要求又易於操作的搭積木的圖紙

演算法:來我們研究下每個積木塊的內部細節,誰能把這些細節做得更優誰就是演算法高手

ACM競賽:來來來!我們來研究下這些幾萬年都不會用到的、幾百年內也難以商業化的積木的內部細節!!!(請輕噴)

科研機構/學校:我們會研究所有積木快包括那些幾百年內也難以商業化的積木的內部細節

大多數公司:我們是搭積木的

少數公司:我們主要也是搭積木的不過我們的積木比較專業所以我們也會做一些針對性很強的一般公司不會用到的積木快的內部細節研究


最近研究大規模計算。。。

反正我覺得和演算法沒啥大關係。。。


我覺得編程能力就是「把演算法轉換成代碼」的能力,所以不包括演算法。而「把需求轉換成演算法」的能力屬於數學建模能力。

因為兩個能力往往需要共同發揮作用,所以廣義地講編程能力是二者之和也沒什麼問題。這並不是一個嚴格的辭彙,不需要過度區分。


什麼才算是真正的編程能力? - 劉賀的回答 - 知乎

這個問題下已經有很多不錯的答案了,題主可以參考一下


不,主要是智商。


不是,還有數據結構。

程序=演算法+數據結構。

以及這年頭會背API都成了能力了?


絕對不止,重裝系統也算呢


計算機的本質都是演算法,但編程不只是演算法,演算法主要集中在基礎平台,如圖像處理演算法,很多成熟的演算法都有演算法庫或開源實現,如FFT演算法。演算法對一個人的編程能力有提升作用,但關靠演算法無法編程,因為編程更像是一門手藝和技術,不光要懂得一些原理,更要有熟能伸巧的運用。

但編程和手藝又不一樣,重要的是代碼累積的最終結果,也就是成品軟體,可能是自用也可能是發布到市場以某種形式使用,大型軟體更像是工程,需要n多人開發,如實現3d作圖的軟體,這樣的大型工程軟體不是一個或兩個編程天才就能完成的,因為人的精力是有限的,需要很多人高度組織管理實現編程才能完成大型複雜的軟體。

看多軟體看上去簡單,但要你要達到產品級,難度是很高。如開發一個簡單記事本幾天完工,但一個比美市場的代碼編輯器,一個人一年都很難完成。因為一個成熟的軟體需要實現很多功能,這些功能不是幾天就能開發好的,需要長期的代碼積累,我覺得寫代碼有點像寫小說,你可能會成語但不一定能寫小說。

但編程和寫小說又不一樣,重要的是編程需要以框架api為基礎,以生成結果為調試參考,以需要為導向,而不是天馬行空想寫什麼寫什麼,需要以計算機環境這個科學實驗的平台為根本,大型軟體需要多人開發,因為工作量實在是太大了,很多大型軟體初期可能是一兩個人開發,但到功能複雜度上升時,需要分散成不同的子功能,而如何分解如何管理又是個很大的問題。

總之編程能力是技術與理論相結合的能力,需要有一定的思維練習與實踐,和大學把一切歸為數學,一切歸為演算法有很大的不同,實際上演算法只是編程的一個鏈環,產業鏈上的一個環,如果所有的底層都是最重要,那歸到最後都是體力活都重要,因為沒人種糧食所有的人都要扼死,計算機的應用越來越廣,演算法在某些領域用處較大,在某些領域用處較少。如果想系統學習計算機編程,最好對一些常用的演算法有了解,這樣有利於整體思維能力的培養與嚴謹性思考。現代演算法已經從以前的單一數學函數演算法中發展出來很多工程實用化演算法,有的形成了演算法框架,如雲計算演算法,大數據演算法,並行演算法,智能處法。演算法中最值得學習的是智能演算法,智能演算法是一種通用演算法思想,是演算法中的精華,有利於提高軟體產品競爭力。發展方向是演算法的雲計算化,並行處理化,微服務化。演算法的本質是在限制條件下追求最優化運算,下面的智能演算法,可以了解一下。

基於仿生/模擬演算法:

人工神經網路

深度學習

遺傳演算法

人工免疫演算法

蟻群演算法

粒子群演算法

人工魚群演算法

文化演算法

禁忌搜索演算法

模擬退火演算法

基於數學理論演算法:

線性規劃

回歸分析

梯度下降

K近鄰演算法

SVM支持向量機

樸素貝葉斯

決策樹

圖論演算法

並行演算法

模糊數學

混沌演算法

馬爾可夫鏈


至少要知道 操作系統、數據結構、計算機組成原理、演算法、資料庫、編程語言、系統架構 等等等等。。。


士兵的作戰能力是否等同射擊水平,恐怕不太好說。

有些東西似乎來自於社會人理解業務的能力、承受挫折的能力、切換各種角度思考問題的能力。


你指廣義的「演算法」的話,是的。

程序 = 演算法 + 數據


不等同於

編程能力包括不管什麼語言打完一行都習慣性加上 ; (而不是初學者那樣忘記打 ; ),包括對各種可能小概率bug的規避,包括同樣是一個函數不用加註釋就能讓別人看的很明白(而不是加了大段注釋別人都看不懂)……

同樣的一個目的,每個人都有不同的實現思路;同樣的思路,每個人寫出來的代碼也不一樣。

思路和代碼的優劣就提現了編程能力


同意 @小狼MOUT 的說法。

我覺得演算法能力和編程能力是兩個不同的概念但又互相交叉融合。

演算法能力更偏向於一種計算機理論,編程思想,和數學,統計有關,注重解決問題的邏輯流程,步驟,訓練人的邏輯思維,能夠使用順序,選擇,循環,遞歸等方法描述出問題求解的本質,是一種對問題進行抽象,然後使用數學與邏輯進行求解的能力;

編程能力更偏向於一種計算機工程,比較寬泛的概念。演算法固然很重要,但是不是衡量編程能力的主要指標,編程能力可能不需要你對某些優化高效演算法有著很深入很透徹的理解,知道基本的數據結構,演算法模型,然後能夠使用自己熟悉的某一門編程語言(熟悉是指熟能生巧,對語法熟悉,對該語言設計理解透徹,對該語言處理數據的某些基本操作了熟於心,信手拈來),快速的對問題進行求解,處理,儘管可能一開始程序效率不是那麼高,但是也有個差不多,主要是能夠快速做出demo,然後後期有計劃的再完善。然後還有一點,對於大型的工程項目,編程能力還體現在出問題能夠快速定位,debug能力要強(儘管搞ACM的很多人都是肉眼調程序,但是畢竟那些問題都是已經細化的各種子問題,搞演算法比較專註於問題求解本身,高效的解決問題是核心,而不用為一些其他的瑣碎事項分心,比如LeetCode的設計就是讓你專註於問題演算法本身,而不用考慮程序的輸入,數據讀取這些瑣事),要善於利用各種框架和庫,對各種工具熟悉,有良好的代碼結構,架構設計,介面設計,模塊化等,要考慮以後的可拓展性blabla……的,是一種綜合能力。可以參考另一問題 什麼才算是真正的編程能力? - 劉賀的回答 - 知乎 。

總結就是,演算法能力是要對問題深入理解,然後進行數學抽象,使用計算機邏輯思維、方法對問題進行求解,能夠寫出詳細偽代碼,並對程序複雜度健壯性心知肚明;而編程能力是一種更加綜合的能力,需要你對編程語言熟悉,能夠快速出demo,出問題快速debug定位,擅用各種框架,庫,開發工具,避免造輪子,要會很多計算機技能。兩者就好比研發與開發的區別,一個需要深度,一個需要廣度。

========================================================================

題外話(引用小狼MOUT的內功比喻):

雖然不能說演算法是編程能力的主體,但是它真的對人鍛煉作用比較大。有點像是武俠小說里的內功與外家功夫。最近看17射鵰,大家都知道,郭靖資質比較愚鈍,學功夫總是要學很多遍,江南七俠教了他十幾年也不見長進,後來全真教馬鈺道長教了他三年內功,于是之後他學其他功夫都突飛猛進。這就好比學過演算法的人上手什麼的都要比沒有學過的人快很多。你學外家功夫,武功招式,劍法刀法可能幾年就會了,可以當街殺人,路見不平,它是一個熟能生巧的過程,只要自己肯學肯練,總能掌握的。但是內功的修鍊卻不是一朝一夕,就像射鵰里郭靖剛學會洪七公的降龍十八掌時,對付江湖上那些武功不是很高的人等綽綽有餘,但是遇到真正的高手(天下五絕之輩)就不行了,而且就算是稍微有點修鍊的歐陽克,也不一定打得過,這都是內功的修鍊。高手過招,表面風平浪靜,背後波濤洶湧。

好了,扯遠了,不喜勿噴。


你跟別人說:我編程能力很強,這種描述很模糊。所以需要一個能夠具化的考量,那麼最能體現編程能力又能考察一個學生的素質和智力又能很好組織的活動自然就是演算法考察了。

但演算法又不完全等同於編程能力,它只是編程能力的一個體現。編程是多方面綜合的結果,實際開發中,除了那種專門做研究的,編程要考慮系統,網路等相關方面綜合設計。

實際上,工作里能用到的演算法少之又少,除非做一些特定研究。大部分用到的都是基本編程素養,但並不是說演算法不需要了。書到用時方恨少,在編演算法上也是這個道理。

這就跟買菜討價還價又不需要會開根號一樣。買菜確實不需要開根號,但你學數學僅僅是為了買菜么。


推薦閱讀:

用 AdBlock 和用盜版軟體有什麼區別?
Mac 有什麼奇技淫巧?
現代 JVM 的垃圾回收裡面還有「引用計數」嗎?
為什麼有人稱甲骨文(Oracle)是業界毒瘤?
如何評價 2015 年 CCPC ?

TAG:演算法 | 編程 | ACM競賽 |