2015 年 10 月,Reddit 有一個激烈的討論帖,名為《這就是初級工程師與高階工程師之間的差距》,好奇開啟一看。發現分享的童鞋是引用了 Thomas A. Limoncelli 在 Quora 上對《從一個無序陣列中查詢最大值的最快演算法是什麼?》的回覆。一起來看看。
Ken Alverson 提到的平行計算的方法可能是最好的演算法答案,而 Tim Farage 的回答可能是對這個這個問題最精確的解釋…. 下面我將給出最實用的答案。
為什麼注重實用?因為由我親自操作,而我生活在一個真實的世界中。在現實生活中,我可以使這個搜尋在 0 秒內完成,甚至不需要任何時間。
在你的職業生涯中,可能從來不需要在完全獨立的情況下進行這個查詢。演算法不是獨立存在的,它們是用在真實世界。真實世界涉及流程,人員和團隊。總有一些外部性的(看似無關的東西)條件可以利用,來獲得比 Ken 和 Tim 的答案更好的結果。
下面是我在職業生涯中作為一個系統管理員的一些案例:
1、對於一個小的數字列表來講,任何演算法都是沒問題的。“小”對於當今世界來講可能就是一千萬個整數。你將會對現代 Intel 處理器遍歷一千萬個數字的速度感到驚訝。如果你只需要一天做一次這樣的查詢操作,搜尋花費的這點時間是微不足道的。不要擔心速度了,等到你覺得它是個問題時再擔心也不遲!時間複雜度為O(N)可能剛剛好。已經記不清有多少次了,總有人跑來對我說“我們需要一個大資料專家”,結果在討論之後,我發現他們所說的“大”只不過是10G的資料。我可以用一張信用卡額度買一臺 Dell 伺服器,然後把這 10G 的資料完全裝載進 RAM 中。
2、可以將查詢操作隱藏在後臺執行。如果搜尋耗費時間太長,看下是否可以在處理程式中儘早獲取陣列,這樣就可以在後臺進行搜尋了。可能是要展示一個標題螢幕,也可能是要渲染一個使用者介面。可以在渲染之前得到陣列嗎?可以的話就可以在後臺進行排序了。縱觀全域性,並查詢所有相關程式最早可以什麼時候得到資料列表。我曾經遇到過這樣一個場景,我們在T+4時得到了一個陣列並在T+6時完成了排序。一個開發者對演算法進行了改進,使得我們在T+5時就可以得到了排好序的資料。我在T+0時就獲得了陣列的訪問權,T+1時刻就把資料準備好了。和v1.0版本的軟體比起來就像是有一臺時間機器!
3、乾脆就不要搜尋了!當你在構建一個list時,總是記錄你遇到的最大值,這樣就可以 O(0)時間內找到最大值了。去告訴負責人然後要求他們這樣做。如果他們不讓步,告訴他們的老闆。是哪個混蛋非要讓你在他們的資料中找到最大值?Oh,他們不能維護一個儲存“最大值”的變數的原因竟是要對這個列表進行刪除和更新操作?如果確實是這樣,他們根本就不應該將資料放到一個無序的陣列中,因為任何其它資料結構對於這些更新操作來說都會是更好的選擇;並且任何其他資料結構都會有一個比 O(N) 更高效的查詢最大值的方法。
4、利用重複的優勢。當你第一次看到這個 list 時,可能確實需要一個線性的時間 O(N) 進行搜尋。然而資料在那之後並不會消失。可能被用來做一些其它的事情,更新,或者修正,這些改變之後需要再次找到最大的值。機會就在這裡,更新操作可以用來跟蹤“最大值”麼?資料稍後會被放到樹或者被排序麼?是否需要精確的答案,或者是否可以根據之前的資料進行估計,然後通過每次重複來改進猜測結果?
我曾經看到有5個執行步驟的程式。每一步由不同的團隊完成。每個團隊都是通過對資料進行排序開始。如果第一個團隊對資料進行了排序,然後為接下來的團隊儲存好排序後的資料,花在排序上的時間將會提高5倍!OMG ,那要求一個團隊的成員來告訴另一個團隊的成員!oh!太恐怖了!拜託拜託!不要讓我做人類了!我只想做一個與世隔絕的碼農!事實上不是這樣的。你想成為一個很棒的程式開發團隊的一員,開發那些由軟體驅動的優秀程式。
因此如果這是一個對功課進行分配的問題…答案是O(N):對 list 做一個線性搜尋,檢查每一個單獨的專案。
如果這個問題是一個誠懇的請求….放下鍵盤。站起來走到大廳中,與所有相關人員交流,挖掘出真正需要的東西,然後重新確定是否確實需要“最大值”,需要它做什麼,以及通過一直追蹤它,整個處理程式是否可以得到改進。
走出你的小黑屋,與人們交流,你將會得到更好的結果。
後續更新:
5、我曾經遇到過這樣的一個場景,發現原來分配記憶體時需要呼叫max()函式。為什麼不基於最後一次得到的相似的dataset進行記憶體大小的增長與收縮?這樣一來,最大值就是一個常量,因此通過提出類似的問題,程式設計師可以以一種完全不同的方式來完成任務。
6、確定後續步驟是否需要一個有序的資料。主動在你這一步將它排好序,這樣就可以通過簡單地獲取最後一個元素來得到最大值。現在這個演算法的複雜度是O(n log2 n)[或者其他排序演算法的複雜度],比 O(n) 更大,但是整個系統卻因此變得更快。
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!
任選一種支付方式