南邮-1205-最大间隙问题

                                                                              最大间隙问题

时间限制(普通/Java) :  4000 MS/ 12000 MS          运行内存限制 : 65536 KByte
总提交 : 227            测试通过 : 69 

比赛描述

         最大间隙问题:给定n 个实数X1 X2 ,Xn,求这n个数在实轴上相邻2个数之间的最大差值。假设对任何实数的下取整函数耗时O(1),设计解最大间隙问题的线性时间算法。

对于给定的n 个实数X1,X2,..., Xn,编程计算它们的最大间隙。



输入

输入数据的第1行有1个正整数n。接下来的1行中有n个实X1 ,X2 ,..., Xn  

输出

 输出最大间隙数

样例输入

5
2.3  3.1  7.5  1.5  6.3 

样例输出

3.2

题目来源

算法设计与实验题解

思路:(参考别人的)

1. 找到n个数据中最大和最小数据maxx和minx;
                                        
2. 用n-2个点等分区间[minx,maxx],即将[minx,maxx]等分为n-1个区间(前闭后开区间),将这些区间看做桶,编号为1,2,...,n-2,n-1,且桶i的上界和桶i+1的下届相同,即每个桶的大小相同;
    每个桶的大小为: dblAvrGap=(maxx-minx)/(n-1)
    实际上,这些桶的边界就构成了一个等差数列(首项为minx,公差d=dblAvrGap),且人为将minx放入第1个桶,将maxx放入第n-1个桶。
                                
    编程实现中,用以下数据结果存放有关桶的数据:
            int *count=new int[n];  //实际分到每个桶的数据个数
            double *low=new double[n]; //实际分到每个桶的最小数据
            double *high=new double[n]; //实际分到每个桶的最大数据
                            
3. 将n个数放入n-1个桶中:
     3.1 按如下规则将x[i]分配到某个桶(编号index)中:  index=int((x[i]-minx)/dblAvrGap)+1;

                若x[i]=minx,则被分到第1个桶中(minx即为桶1的下界);
                若x[i]=桶j的下界(也是桶j-1的上界),则被分到桶j中(j>=1);
                若x[i]=maxx,则被分到桶n中(max为桶n的下界桶n-1的上界),但没有桶n,解决办法:
                        可人为将其移入桶n-1中或者再加一个桶,这并不影响求其最大间隙;
                                           
      3.2 调整分到该桶的最大最小数据;
                                                                
4. 求最大间隙:
      除最大最小数据maxx和minx以外的n-2个数据被放入n-1个桶中,由抽屉原理可知至少有一个桶是空的;
      又因每个桶的大小相同,所以最大间隙不会在同一桶中出现;
      一定是某个桶的上界(dblHigh)和其后某个桶的下界(dblLow)之间隙,且该两桶之间的桶(即编号在该两桶编号之间的桶)一定是空桶;
      即最大间隙在桶i的上界和桶j的下界之间产生(j>=i+1);
代码:
#include<iostream>
using namespace std;

//函数模板求最小值 
template<class T>
int mini(int n, T* x)
{
	T tmp = x[1];
	int k=1;
	for (int i = 1; i <= n; i++)
	{
		if (x[i] < tmp) 
		{
			tmp = x[i];
			k = i;
		}
	}
	return k;
}

//函数模板求最大值  
template<class T>
int maxi(int n, T* x)
{
	T tmp = x[1];
	int k = 1;
	for (int i = 1; i <= n; i++)
	{
		if (x[i] > tmp) 
		{
			tmp = x[i];
			k = i;
		}
	}
	return k;
}

//算法
double maxgap(int n, double* x)
{
	double minx = x[mini(n, x)];
	double maxx = x[maxi(n, x)];

	//用n-2个等间距点分割区间[minx, maxx]
	//产生n-1个桶,每个桶i中用high[i]和low[i]
	//分别存储分配给桶i的数中最大数和最小数

	int* ncount = new int[n + 1];
	double* low = new double[n + 1];
	double* high= new double[n + 1];

	//桶初始化
	for (int i = 1; i <= n - 1; i++)
	{
		ncount[i] = 0;
		low[i] = maxx;
		high[i] = minx;
	}

	//将n个数置于n-1个桶中
	for (int i = 1; i <= n; i++)
	{
		int bucket = int((n-1) * (x[i]-minx) / (maxx-minx)) + 1;
		ncount[bucket]++;
		if (x[i] < low[bucket]) low[bucket] = x[i];
		if (x[i] > high[bucket]) high[bucket] = x[i];
	}

	//此时,除了maxx和minx外的n-2个数被置于n-1个桶中。
	//由抽屉原理即知,至少有一个桶是空的。
	//这意味着最大间隙不会出现在同一桶中的两个数之间。
	//对每一个桶做一次线性扫描即可找出最大间隙。

	double tmp = 0;
	double left = high[1];

	for (int i = 2; i <= n; i++)
	{
		if (ncount[i])
		{
			double gap = low[i] - left;
			if (gap > tmp) tmp = gap;
			left = high[i];
		}
	}
	return tmp;
}

int main()
{
	//进行输入 
	int num;
	cin >> num;
	double* pdArr = new double[num+1];
	for (int i = 1; i <= num; i++)
	{
		cin >> pdArr[i];
	}
	cout << maxgap(num, pdArr)<<endl;
	system("pause");
	return 0;
}
总结:

本程序使用了桶排序思想,建立桶,但分别用三个数组为桶分配最大值,最小值和统计个数,值得一提的是鸽笼原理的使用,因为如果n-2个数分配到n-1个桶里面,一定是最大间隙出现在不同桶,因为中间间隔一个桶的长度,致使必须是分开的桶中相邻数据存在最大间隙。但不能忽略首尾情况。也就是说把n个数分配到n个桶里面,第n个桶只装边界值,因为每个桶利用公式 int((n-1) * (x[i]-minx) / (maxx-minx)) + 1。结果确定的区间是[    ),左开右闭,必须多设置一个装最大边界值的桶。原书作者出错了,忽略了边界情况,如上红体标出,对第n个桶的边缘也需要检测gap大小。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值