問題:尋找數組中的最小值和最大值。
一道很簡單的題目,一般有下面4種解法:
1 遍歷兩次,每次分別找出最小值和最大值。
2 只遍歷一次,每次取出的元素先與已找到的最小值比較,再與已找到的最大值比較。
3 每次取兩個元素,將較小者與已找到的最小值比較,將較大者與已找到的最大值比較。
4 分治:將數組劃分成兩半,分別找出兩邊的最小值、最大值,則最小值、最大值分別是兩邊最小值的較小者、兩邊最大值的較大者。
這4種算法,哪種效率最高,哪種最低?
後兩種算法只要進行1.5*N次比較,因而網上有不少解答都將它們列為最佳答案。但是,算法4用到了遞歸,而遞歸法函數調用的開銷是很大的,這就注定了該算法的效率肯定不高。那麼,算法3就是最高效的嗎?還是用代碼來驗證吧。
後面的代碼,對每種算法都實現了兩個函數(假設數組長度為N):
算法1:solve_1a與solve_1b,後者加入兩個臨時變量,編譯器可以將變量儲存在寄存器中,不用每次循環都要寫內存。比較次數為2*N次。
算法2:solve_2a與solve_2b,前者每次循環必比較2次,後者最好情況下(遞減數組)只要比較1次,但最差情況下(遞增數組)則要比較2次,比較次數為:N到2 * N次。
算法3:solve_3a與solve_3b,前者每次循環取頭尾兩元素(從兩頭往中間取),後者取相鄰兩元素。比較次數為1.5 * N次。
算法4:solve_4a與solve_4b,後者返回一個結構(只有兩個元素),編譯器優化可以通過兩個寄存器返回該結構,減少寫內存次數。(檢查gcc產生的匯編,確認有進行該優化)。比較次數為1.5 * N次。
下面是測試結果:(數組長度為6e7,每種測4次取平均值)
所用時間(毫秒,GCC 4.5)
所用時間(毫秒,VC 2010)
函數名
遞增
遞減
亂序1
亂序2
亂序3
遞增
遞減
亂序1
亂序2