又是小程講道理的時間,如果根本就不對你的口味請直接離開。講什麼道理呢,就是對演算法的理解,演算法是什麼,有什麼用,怎麼學習演算法。

上一次講了遞歸的簡單入門,說遞歸是重要而實用的演算法套路。那為什麼遞歸是演算法先?

(1)演算法是什麼?

演算法就是設計好的計算流程。

首先,演算法是經過設計的,是為了解決某個或某類問題的,是有考慮資源成本的,等等。那些不知道為何而做的,隨遇而安的,不是演算法。

然後,演算法是計算流程。計算是一個抽象概念,形式上可以是數值運算,也可以是調配資源,也可以是攻城奪寨,等等。而流程,就是操作步驟。

再簡單一點,突出重點,演算法就是經過設計的東西。你要有設計,不是說想到哪做到哪,不是「自然而然」的行動,當然,如果你的直覺充滿了設計,你是天生的設計師,那不能否認你的「邊做邊想」也是演算法,只不過你沒有提煉出來而已。

按鍵的設計意圖

另一個問題,演算法跟程序是什麼關系?

有人曾說過:程序=數據結構+演算法,所以要寫好程序就要演算法好。我並不同意這種說話,我認為程序跟演算法沒有必然的聯系,我認為,程序=變量+流程,很多時候,寫好程序只要理解業務跟需求,並且掌握編程工具,就可以做到,並不需要你有設計演算法的能力。同樣,演算法設計好,也不一定能把程序寫好,你可能根本就不懂編程工具,還寫什麼程序。

所以,設計是設計,寫程序是寫程序,沒有必然關系的,你可以專做演算法設計而不寫代碼。只不過,一般像我們這些一線開發,設計跟編程是同一個人,所以才有演算法設計跟編程一起來的情況,像那些高級的,他們很可能只扔給你一個演算法,由你來編程實現,這時兩者就明顯分開(設計者有可能不懂編程)。

既然演算法就是事先設計,那這個設計有用嗎?

(2)演算法有沒有用?

這個問題很好回答,從大局來說,從行業、技術的發展來說,演算法一定是一個關鍵元素。

那對於個人呢,演算法設計是不是有用?

你可能會覺得,只有跟我相關的演算法才有用,比如,如果我整天都是寫Android平台的activity,那我理解視訊的壓縮演算法又能帶來什麼幫助呢?如果我的職責就是優化視訊首幀的顯示速度,那理解壓縮演算法就可能有幫助了。所以你可能會得出一個結論:只有跟我相關的演算法才有用。

我覺得跟你相關的演算法能直接幫助到你的,而跟你不相關的演算法的理解也一樣能幫助到你。正如之前所說,具體的事情本身往往不是關注點,關注點在於做這個事情的過程中強化什麼。

所以,沒有疑問,演算法設計是有用的,退一萬步來說,你對設計的思考能讓你保持獨立思考與堅持苦想的習慣。而且你會發現,現實工作環境中,懂演算法的人更能通殺不同的平台(所以工資高唄),畢竟設計套路很多是相通的。

開了一會小差

既然演算法設計能幫到我們,甚至某些場合是必須的,那應該怎麼去學習演算法呢?畢竟那麼多演算法設計!

(3)怎麼學習演算法?

就像武俠小說中的太祖長拳、羅漢拳一樣,演算法是套路。你應該學習的是設計套路,至於怎麼把多個套路組合,怎麼分拆成散打,那是參悟的問題。

學習演算法,主要還是學習經典的套路,比如分治思想、貪婪演算法、回溯法,等等,而對於專門領域的演算法,你可能要學得更加具體(這個過程足夠強化你的苦想能力)。

不要學那些「抖機靈的演算法」,有些「演算法」只是編程技術的巧妙運用,並不是套路。包括很多演算法題目,都沒有引導大家去學習演算法套路,而只是強調編程技巧。編程技巧有可能是重要的,但跟學習演算法沒有關系,應該摒棄這個干擾。

比如,這樣一個題目:

逆轉單向鏈表。

如果從「分治」與「復用」的套路出發,就會把問題簡化為「如何把兩個結點逆轉」,兩個結點逆轉是容易實現的。當兩個結點逆轉後,問題再次變成了「如何把兩個結點逆轉」,只不過是指嚮往前推進了。

如果「抖機靈」,使用編程技巧,可以先把所有結點的地址保存到數組,然後循環數組,讓a[i]->next = a[i-1],留意邊界,即可。但是,編程技巧不是演算法套路,不應該出現在演算法設計上。

另外,專門領域的演算法,比如視訊壓縮、搜索引擎等演算法,也是套路,而且是實戰性很強的套路。

總的來說,你應該學習經典的演算法套路,並且忽略編程技巧類的干擾,畢竟在這里,我們學的是設計,而不是編程。

funny_5

總結一下,又是講道理,回答了「演算法是什麼」、「有沒有用」、「怎麼學習」這三個問題。演算法就是設計,是我們的朋友,要跟經典的演算法套路打交道。


wakeup