【算法拾遗】最大数和最小数

转载请注明出处: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

    

posted on 2017-06-02 12:21  slgkaifa  阅读(609)  评论(0编辑  收藏  举报

导航