【算法拾遗】最大数和最小数
转载请注明出处: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