【算法拾遺】最大數和最小數
轉載請註明出處:http://blog.csdn.net/ns_code/article/details/28735533
求一個數組中的最大值和最小值。我們一般的做法是掃描一遍數組求的最大值,掃描一遍數組求最小值,這樣做須要比較2N次才幹求解。
而實際上我們能夠比較1.5N次就可以得到結果。考慮例如以下幾種方法。
方法一:
我們能夠把數組分成兩部分。首先依照順序將數組中的相鄰的兩個數分在同一組,接著比較同一組中奇數位上的值和偶數位上的值,將較大的放在偶數位上,較小的放在奇數位上,這樣經過0.5N次比較後,最大數肯定在偶數位上,最小的數肯定在奇數位上。而後分別掃描一遍數組的偶數位和奇數位,便可得到最大值和最小值。這樣,真個算法僅僅需比較1.5N次。代碼非常easy,不再給出。
方法二:
方法一會破壞原數組的結構,要避免這個問題,我們給出方法二。
首先仍依照順序將相鄰的兩個元素劃為一組。而後利用兩個變量max和min保存當前的最大值和最小值。同一組的數比較之後,不再交換位置,而是將當中較小的數與min作比較,假設小於min則更新min,同理將當中較大的數與max作比較,假設大於max則更新max。
這樣依舊共同擁有0.5N組,每一組的兩個元素比較。要比較0.5N次。max與該組較大者比較,共比較0.5N次。min與該組最小者比較,共比較0.5N次,一共也是1.5N次。代碼相同非常easy,不再給出。
方法三:
能夠用分治的思想,僅僅需分別求出數組前後N/2個數中的最大值和最小值。而後取兩個大值中最大值最為max,去兩個小值中的最小值為min。該方法相同要比較N/2次。
實現代碼例如以下:
/* 分治法求最大最小值 */ void SearchMaxAndMin(int *arr,int start,int end,int *min,int *max) { if(arr == NULL) return; if(end-start <=1) { if(arr[start]>arr[end]) { *max = arr[start]; *min = arr[end]; } else { *max = arr[end]; *min = arr[start]; } return; } int maxL,minL; int maxR,minR; SearchMaxAndMin(arr,start,(start+end)>>1,&minL,&maxL); //求左邊最大最小值 SearchMaxAndMin(arr,((start+end)>>1)+1,end,&minR,&maxR); //求右邊最大最小值 if(maxL>maxR) *max = maxL; else *max = maxR; if(minL<minR) *min = minL; else *min = minR; }
延伸
求數組中的第二大的數,假設我們先掃描一遍數組。求的最大值。而後將其放到數組的最後,再求剩下元素的最大值,這樣依舊要比較2N-1次。
我們能夠通過設置兩個變量max1和max2分別保存最大值和次大值,將數組的前兩個值中大的賦給max1。小的賦給max2,遇到某個元素大於max1。則更新max1,假設某元素大於max2。小於max1,則更新max2,這樣到最後遍歷一遍便能夠得出次大值。但這樣由於每一個元素要與兩個值比較,因此比較次數依舊為2N。
相同能夠利用解法二相似的方法,將比較次數降到1.5N次。將min改為max2。改變max2的更新條件就可以。
依舊也能夠用分治的策略,比較前後N/2個數中的最大值和次大值,二者均取最大的那個,這樣比較次數依舊為1.5N.
而要求數組中的第k大的數。能夠參考我的這篇博文:http://blog.csdn.net/ns_code/article/details/26966159
【算法拾遺】最大數和最小數