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

来源:互联网 发布:淘宝包包代理厂家直销 编辑:程序博客网 时间:2024/04/29 14:58

转载请注明出处:http://blog.csdn.net/ns_code/article/details/28735533


    求一个数组中的最大值和最小值,我们一般的做法是扫描一遍数组求的最大值,扫描一遍数组求最小值,这样做需要比较2N次才能求解。而实际上我们可以比较1.5N次即可得到结果。考虑如下几种方法。


    方法一:

    我们可以把数组分成两部分,首先按照顺序将数组中的相邻的两个数分在同一组,接着比较同一组中奇数位上的值和偶数位上的值,将较大的放在偶数位上,较小的放在奇数位上,这样经过0.5N次比较后,最大数肯定在偶数位上,最小的数肯定在奇数位上,而后分别扫描一遍数组的偶数位和奇数位,便可得到最大值和最小值。这样,真个算法只需比较1.5N次。代码很简单,不再给出。


    方法二:

    方法一会破坏原数组的结构,要避免这个问题,我们给出方法二。首先仍按照顺序将相邻的两个元素划为一组,而后利用两个变量max和min保存当前的最大值和最小值,同一组的数比较之后,不再交换位置,而是将其中较小的数与min作比较,如果小于min则更新min,同理将其中较大的数与max作比较,如果大于max则更新max。这样依然共有0.5N组,每一组的两个元素比较,要比较0.5N次,max与该组较大者比较,共比较0.5N次,min与该组最小者比较,共比较0.5N次,一共也是1.5N次。代码同样很简单,不再给出。


    方法三:

    可以用分治的思想,只需分别求出数组前后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

    

2 1
原创粉丝点击