您的位置:首页 > 编程语言

编程之美:第二章 数字之魅 2.10寻找数组中的最大值和最小值

2015-08-03 01:03 453 查看
/*
寻找数组中的最大值和最小值:
对于一个由N个整数组成的数组,需要比较多少次才能把最大和最小的数找出来呢?
例如给出数组{5,6,8,3,7,9}

分析:
解法1:
可以把寻找数组中的最大值和最小值看成两个独立的问题,分别求解即可。最直接的做法是先扫描一次数组,找出最大的数和最小的数。需要比较2*N次才能求解。
不需要用排序做,设定一个最大值和一个最小值即可

解法2:
最大的数和最小的数一半不是同一个数,(除非N=1,或者所有整数都是一样的大小)。先把数组分成两部分,然后再从这两部分中分别找出最大的数和最小的数。
首先按照顺序将数组中相邻的两个数分在同一组。若数组为{5,6,8,3,7,9},接着比较同一组中奇数位数字和偶数位数字,将较大的数放在偶数位上,较小的数放在奇数
位上。经过N/2次比较,较大的数都放到了偶数位置上,最后从奇偶数位上分别求出Max = 9,Min = 3,各需要比较N/2次。
总共需要比较1.5*N次。

解法3:
解法2破坏了原数组。如果可以在遍历的过程中进行比较,且不对数组中的元素进行交换,就不会破坏原数组。仍然按照顺序将数组中相邻的两个数分在同一组
,然后可以利用两个变量来Max和Min来存储当前的最大值和最小值。同一组的两个数比较之后,不再调整顺序,而是将其中较大的数与当前Max比较。如果该数
大于当前Max,则更新Max

解法4:
分治思想。在N个数中求最小值Min和最大值Max,我们只需分别求出前后N/2个数的Min和Max,然后取较小的Min,较大的Max即可

输入:
6
5 6 8 3 7 9
输出:
3 9
*/

/*
1 		if(pArr[i] < pArr[i+1])//前面小于后面,则交换,确保较大的数在偶数位上
		{
			swap(&pArr[i],&pArr[i+1]);
		}
2 		if(pArr[j] < iMin)//接下来在奇数位上寻找最小数,
		{
			iMin = pArr[j];
		}
3 		if(pArr[i] < pArr[i+1])//保持原来数组中的顺序,采用记录初始化的Max和Min的做法
		{
			iMin = min(pArr[i],iMin);
			iMax = max(pArr[i+1],iMax);
		}
4 	if(high - low <= 1)
	{
		if(pArr[low] < pArr[high])
		{
			return make_pair<int,int>(pArr[low],pArr[high]);
5 		pair<int,int> pairLeft = findMinMax_recursion(pArr,low,low + (high - low)/2);
		pair<int,int> pairRight = findMinMax_recursion(pArr,low + (high - low)/2 + 1,high);
*/
#include <stdio.h>
#include <iostream>

using namespace std;
const int MAXSIZE = 10000;

void swap(int* pNum1,int* pNum2)
{
	int iTemp  = *pNum1;
	*pNum1 = *pNum2;
	*pNum2 = iTemp;
}

pair<int,int> findMinMax_divide(int* pArr,int iLen)//采用较大数放在偶数位上的方法,共需要比较1.5*N次
{
	int i,j;
	for(i = 0 ; i < iLen; i += 2)
	{
		if(pArr[i] < pArr[i+1])//前面小于后面,则交换,确保较大的数在偶数位上
		{
			swap(&pArr[i],&pArr[i+1]);
		}
	}
	int iMin = pArr[1],iMax = pArr[0];
	for(i = 0,j = i + 1; i < iLen ; i += 2, j += 2)
	{
		if(pArr[i] > iMax)
		{
			iMax = pArr[i];
		}
		if(pArr[j] < iMin)//接下来在奇数位上寻找最小数,
		{
			iMin = pArr[j];
		}
	}
	return make_pair<int,int>(iMin,iMax);
}

pair<int,int> findMinMax_recursion(int* pArr,int low,int high)
{
	if(high - low <= 1)
	{
		if(pArr[low] < pArr[high])
		{
			return make_pair<int,int>(pArr[low],pArr[high]);
		}
		else
		{
			return make_pair<int,int>(pArr[high],pArr[low]);
		}
	}
	else
	{
		int iMin,iMax;
		pair<int,int> pairLeft = findMinMax_recursion(pArr,low,low + (high - low)/2);
		pair<int,int> pairRight = findMinMax_recursion(pArr,low + (high - low)/2 + 1,high);
		if(pairLeft.first < pairRight.first)
		{
			iMin = pairLeft.first;
		}
		else
		{
			iMin = pairRight.first;
		}
		if(pairLeft.second > pairRight.second)
		{
			iMax = pairLeft.second;
		}
		else
		{
			iMax = pairRight.second;
		}
		return make_pair<int,int>(iMin,iMax);
	}
}

int min(int a,int b)
{
	return a < b ? a : b;
}

int max(int a,int b)
{
	return a > b ? a : b;
}

pair<int,int> findMinMax_keppSeq(int* pArr,int iLen)
{
	int i,j,iMin,iMax;
	iMin = min(pArr[0],pArr[1]);
	iMax = max(pArr[0],pArr[1]);
	for(i = 2 ; i < iLen ; i += 2)
	{
		if(pArr[i] < pArr[i+1])//保持原来数组中的顺序,采用记录初始化的Max和Min的做法
		{
			iMin = min(pArr[i],iMin);
			iMax = max(pArr[i+1],iMax);
		}
		else
		{
			iMin = min(pArr[i+1],iMin);
			iMax = max(pArr[i],iMax);
		}
	}
	return make_pair<int,int>(iMin,iMax);
}

void process()
{
	int n;
	while(EOF != scanf("%d",&n))
	{
		int iArr[MAXSIZE];
		for(int i = 0 ; i < n; i++)
		{
			scanf("%d",&iArr[i]);
		}
		//pair<int,int> pairRes = findMinMax_divide(iArr,n);
		//pair<int,int> pairRes = findMinMax_keppSeq(iArr,n);
		pair<int,int> pairRes = findMinMax_recursion(iArr,0,n-1);//shi 
		printf("%d %d\n",pairRes.first,pairRes.second);
	}
}

int main(int argc,char* argv[])
{
	process();
	getchar();
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: