有一天跟老婆一起讀唐詩,看到李白的俠客行:
趙客縵胡纓,吳鉤霜雪明。銀鞍照白馬,颯沓如流星。
十步殺一人,千里不留行。事了拂衣去,深藏身與名。
閒過信陵飲,脫劍膝前橫。將炙啖朱亥,持觴勸侯嬴。
三杯吐然諾,五岳倒為輕。眼花耳熱後,意氣素霓生。
救趙揮金錘,邯鄲先震驚。千秋二壯士,烜赫大樑城。
縱死俠骨香,不慚世上英。誰能書閣下,白首太玄經。
然後有以下對話:
我:你最喜歡哪一句?
老婆:「千里殺一人」那句。
我:你是說「十步殺一人,千里不留行」?
老婆:對。
後面的對話是討論詩本身了。然而當時我腦海裡立刻想到的是:將「十步殺一人,千里不留行」精簡為「千里殺一人」,雖然變短了,卻帶來了嚴重的效能問題。之前按十步一人算,千里可以殺好多人,而現在只殺一人,效率大大降低。降低多少呢?假設一步為0.5m,之前千里可以殺100000人,現在是1人,十萬倍!
演算法常常是這樣的。一段歸併排序的**跟選擇排序相比,雖然長了一些,卻在基數足夠大的情況下確實可以帶來100000倍的效能提公升。在技術上,一旦遇到的效能問題,常見的思路就是用更複雜的**來改善效能。比如資料庫查詢不夠快,我們可能會去加索引。而索引的本質就是維護乙個資料結構(常常是b-tree),在搜尋的時候利用這個資料結構快速定位到要找的資料。於是更加複雜的**(索引的維護和利用)帶來了效能的飛躍。
複雜的演算法絕不是能用一句話說清楚非要用三句話來說,而是在沒有**冗餘,沒有精簡的餘地時,有更多的處理邏輯和更精密的資料結構。一些精妙的演算法確實精簡的堪比藝術品,然而其背後的思想和推導過程絕非想當然地就能得到。解決一些現實問題常常不得不把一些簡單的概念複雜化。從扁平結構到關係結構,從直接獲取到使用**,從單點到集群等等,舉不勝舉。
然而,這正是程式設計師的使命:面對漸漸浮現的,或者未來即將出現的複雜問題,分析,建模,解決掉它們。在技術的道路上,真的猛士敢於直面複雜的問題,寫下精簡的**。
十步殺一人,千里不留行
傳說莊子是乙個劍客,十步殺一人,千里不留行 可謂 天下無敵 魏王聽說後艷羨不已,問莊子以劍道。莊子自言劍道有三。名曰 天子劍 諸侯劍 庶人劍。天子之劍,以燕溪石城為鋒,齊岱為鍔,晉魏為脊,周宋為鐔,韓魏為夾 包以四夷,裹以四時,繞以渤海,帶以常山 制以五行,論以刑德 開以陰陽,持以春秋,行以秋冬。此...
「一步千里」之陣列找數
歡迎關注微博 有這樣乙個陣列a,大小為n,相鄰元素差的絕對值都是1。如 a 現在,給定a和目標整數t,請找到t在a中的位置。除了依次遍歷,還有更好的方法麼?這道題目的解法非常有趣。陣列第乙個數為array 0 要找的數為y,設t abs y array 0 由於每個相鄰的數字之差的絕對值為1。故第t...
「一步千里」之陣列找數
有這樣乙個陣列 a,大小為 n,相鄰元素差的絕對值都是 1。如 a 現在,給定 a和目標整數 t,請找到t在 a中的位置。除了依次遍歷,還有更好的方法麼?這道題目的解法非常有趣。陣列第乙個數為array 0 要找的數為y,設t abs y array 0 由於每個相鄰的數字之差的絕對值為1。故第t個...