咱們的公眾號有很多硬核的算法文章,今天就聊點輕松的,就具體聊聊我非常“鼓吹”的《算法4》。這本書我在之前的文章多次推薦過,但是沒有具體的介紹,今天就來正式介紹一下。。
我的推薦不會直接甩一大堆書目,而是會聯系實際生活,講一些書中有趣有用的知識,無論你最后會不會去看這本書,本文都會給你帶來一些收獲。
首先這本書是適合初學者的。總是有很多讀者問,我只會 C 語言,能不能看《算法4》?學算法最好用什么語言?諸如此類的問題。
經常看咱們公眾號的讀者應該體會到了,算法其實是一種思維模式,和你用什么語言沒啥關系。我們的文章也不會固定用某一種語言,而是什么語言寫出來容易理解就用什么語言。再退一步說,到底適不適合你,網上找個 PDF 親自看一下不就知道了?
《算法4》看起來挺厚的,但是前面幾十頁是教你 Java 的;每章后面還有習題,占了不少頁數;每章還有一些數學證明,這些都可以忽略。這樣算下來,剩下的就是基礎知識和疑難解答之類的內容,含金量很高,把這些基礎知識動手實踐一遍,真的就可以達到不錯的水平了。
我覺得這本書之所以能有這么高的評分,一個是因為講解詳細,還有大量配圖,另一個原因就是書中把一些算法和現實生活中的使用場景聯系起來,你不僅知道某個算法怎么實現,也知道它大概能運用到什么場景,下面我就來介紹兩個圖算法的簡單應用。
一、二分圖的應用
我想舉的第一個例子是二分圖。簡單來說,二分圖就是一幅擁有特殊性質的圖:能夠用兩種顏色為所有頂點着色,使得任何一條邊的兩個頂點顏色不同。

明白了二分圖是什么,能解決什么實際問題呢?算法方面,常見的操作是如何判定一幅圖是不是二分圖。比如說下面這道 LeetCode 題目:

你想想,如果我們把每個人視為一個頂點,邊代表討厭;相互討厭的兩個人之間連接一條邊,就可以形成一幅圖。那么根據剛才二分圖的定義,如果這幅圖是一幅二分圖,就說明這些人可以被分為兩組,否則的話就不行。
這是判定二分圖算法的一個應用,其實二分圖在數據結構方面也有一些不錯的特性。
比如說我們需要一種數據結構來儲存電影和演員之間的關系:某一部電影肯定是由多位演員出演的,且某一位演員可能會出演多部電影。你使用什么數據結構來存儲這種關系呢?
既然是存儲映射關系,最簡單的不就是使用哈希表嘛,我們可以使用一個 HashMap<String, List<String>>
來存儲電影到演員列表的映射,如果給一部電影的名字,就能快速得到出演該電影的演員。
但是如果給出一個演員的名字,我們想快速得到該演員演出的所有電影,怎么辦呢?這就需要「反向索引」,對之前的哈希表進行一些操作,新建另一個哈希表,把演員作為鍵,把電影列表作為值。
對於上面這個例子,可以使用二分圖來取代哈希表。電影和演員是具有二分圖性質的:如果把電影和演員視為圖中的頂點,出演關系作為邊,那么與電影頂點相連的一定是演員,與演員相鄰的一定是電影,不存在演員和演員相連,電影和電影相連的情況。
回顧二分圖的定義,如果對演員和電影頂點着色,肯定就是一幅二分圖:

如果這幅圖構建完成,就不需要反向索引,對於演員頂點,其直接連接的頂點就是他出演的電影,對於電影頂點,其直接連接的頂點就是出演演員。
當然,對於這個問題,書中還提到了一些其他有趣的玩法,比如說社交網絡中「間隔度數」的計算(六度空間理論應該聽說過)等等,其實就是一個 BFS 廣度優先搜索尋找最短路徑的問題,具體代碼實現這里就不展開了。
二、套匯的算法
如果我們說貨幣 A 到貨幣 B 的匯率是 10,意思就是 1 單位的貨幣 A 可以換 10 單位貨幣 B。如果我們把每種貨幣視為一幅圖的頂點,貨幣之間的匯率視為加權有向邊,那么整個匯率市場就是一幅「完全加權有向圖」。
一旦把現實生活中的情景抽象成圖,就有可能運用算法解決一些問題。比如說圖中可能存在下面的情況:

圖中的加權有向邊代表匯率,我們可以發現如果把 100 單位的貨幣 A 換成 B,再換成 C,最后換回 A,就可以得到 100×0.9×0.8×1.4 = 100.8 單位的 A!如果交易的金額大一些的話,賺的錢是很可觀的,這種空手套白狼的操作就是套匯。
現實中交易會有種種限制,而且市場瞬息萬變,但是套匯的利潤還是很高的,關鍵就在於如何快速找到這種套匯機會呢?
借助圖的抽象,我們發現套匯機會其實就是一個環,且這個環上的權重之積大於 1,只要在順着這個環交易一圈就能空手套白狼。
圖論中有一個經典算法叫做 Bellman-Ford 算法,可以用於尋找負權重環。對於我們說的套匯問題,可以先把所有邊的權重 w 替換成 -ln(w),這樣「尋找權重乘積大於 1 的環」就轉化成了「尋找權重和小於 0 的環」,就可以使用 Bellman-Ford 算法在 O(EV) 的時間內尋找負權重環,也就是尋找套匯機會。
《算法4》就介紹到這里,關於上面兩個例子的具體內容,可以自己去看書,公眾號后台回復關鍵詞「算法4」就有 PDF。
三、最后說幾句
首先,前文說對於數學證明、章后習題可以忽略,可能有人要抬杠了:難道習題和數學證明不重要嗎?
那我想說,就是不重要,起碼對大多數人來說不重要。我覺得吧,學習就要帶着目的性去學,大部分人學算法不就是鞏固計算機知識,對付面試題目嗎?如果是這個目的,那就學些基本的數據結構和經典算法,明白它們的時間復雜度,然后去刷題就好了,何必和習題、證明過不去?
這也是我從來不推薦《算法導論》這本書的原因。如果有人給你推薦這本書,只可能有兩個原因,要么他是真大佬,要么他在裝大佬。《算法導論》中充斥大量數學證明,而且很多數據結構是很少用到的,頂多當個字典用。你說你學了那些有啥用呢,饒過自己唄。
另外,讀書在精不在多。你花時間《算法4》過個大半(最后小半部分有點困難),同時刷點題,看看咱們的公眾號文章,算法這塊真就夠了,別對細節問題太較真。
我最近精心制作了一份電子書《labuladong的算法小抄》,分為【動態規划】【數據結構】【算法思維】【高頻面試】四個章節,共 60 多篇原創文章,絕對精品!限時開放下載,在我的公眾號 labuladong 后台回復關鍵詞【pdf】即可免費下載!
歡迎關注我的公眾號 labuladong,技術公眾號的清流,堅持原創,致力於把問題講清楚!