1. 程式人生 > >【算法拾遺】最大數和最小數

【算法拾遺】最大數和最小數

eas null 第k大 方法 track 兩個 str 最大值和次大值 數位

轉載請註明出處: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

【算法拾遺】最大數和最小數