最大间隙问题-鸽舍原理

最大间隙问题

问题描述:

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

算法输入:

5

2.3  3.1  7.5  1.5  6.3

算法输出:

3.2

要想解决这个问题,最直观的解决方法就是将n个实数排序之后,线性寻找两两之间间隔的最大值。然而排序算法最好的复杂度是O(nlog(n))(因为排序算法最好的复杂度就是O(nlog(n))),所以这个方法可以排除了。而要保证线性时间,就得使用到鸽舍原理。

 

鸽舍原理

1. 把n+1个元素分成n类,不管怎么分,则一定有一类中有2个或2个以上的元素

2. 把多于m×n个物体放到n个抽屉里,那么一定有一个抽屉里有m+1个或者m+1个以上的物体

 

算法分析

1. 找出数组中的最小值和最大值

2. 创建n-1个桶并初始化,每个桶的小值放数组最大值,大值放数组的最小值

3. 根据数组中n个元素的相对大小,将他们放在这n-1个桶中,可能有的桶中为空值,可能有的桶中含有多个元素,并记录每一个桶的小值和大值

4. 用后一个桶的小值减去上一个桶的大值,得到桶之间的间隙,最后取出最大的那个间隙(前提:易知最大间隙一定大于等于n个元素的平均距离,所以桶内的元素间隙一定不是最大间隙,最大间隙只能在桶间)

 

C++代码

#include 
#include 
#include 
#include 
using namespace std;

//返回数组中最小元素的下标
template
int mini(int n, T* x)
{
	T temp = x[0];
	int k = 0;
	for (int i = 1; i < n; i++)
	{
		if (x[i] < temp)
		{
			temp = x[i];
			k = i;
		}
	}
	return k;
}

//返回数组中最大元素的下标
template
int maxi(int n, T* x)
{
	T temp = x[0];
	int k = 0;
	for (int i = 1; i < n; i++)
	{
		if (x[i] > temp)
		{
			temp = 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-1个桶,每个桶有一个最小值和最大值
	int *count = new int[n - 1];
	double *low = new double[n - 1];
	double *high = new double[n - 1];

	//初始化这n-1个桶,数组最大值赋给每个桶的小值
	//数组最小值赋给每个桶的大值
	for (int i = 0; i < n - 1; i++)
	{
		count[i] = 0;
		low[i] = maxx;
		high[i] = minx;
	}

	//将数组中的n个元素分配n-1个桶中,并记录每个桶中的小值和大值
	for (int i = 0; i < n; i++)
	{
		//bucket是指每个元素应分到哪个桶的ID(ID=[0,1,...,n-2])
		//bucket = (x[i] - minx) / 平均距离
		//       = (x[i] - minx) / ((maxx - minx) / (n - 1))
		//       = (n - 1) * (x[i] - minx) / (maxx - minx)
		//int起着向下取整的作用
		int bucket = int((n - 1) * (x[i] - minx) / (maxx - minx));
		//当x[i] = maxx时,bucket向下取整会取到n-1
		//为了避免越界,强行将数组最大元素放在最后一个桶中
		if (bucket == (n - 1))
			bucket = n - 2;
		count[bucket]++;
		if (x[i] < low[bucket])
			low[bucket] = x[i];
		if (x[i] > high[bucket])
			high[bucket] = x[i];
	}

	double temp = 0;
	double left = high[0];
	for (int i = 1; i < n - 1; i++)
	{
		if (count[i])
		{
			double thisgap = low[i] - left;
			if (thisgap > temp)
				temp = thisgap;
			left = high[i];
		}
	}
	return temp;
}

int main()
{
	string infile_name = "input.txt";
	string outfile_name = "output.txt";
	int n;
	double a[100];
	double result;

	//读取文件
	ifstream infile;
	infile.open(infile_name, ios::in);
	assert(infile.is_open());
	infile >> n;  //给参数n赋值
	//给数组a赋值
	for (int i = 0; i < n; i++)
		infile >> a[i];
	infile.close();
	
	//计算
	result = maxgap(n, a);

	//保存结果
	ofstream outfile;
	outfile.open(outfile_name, ios::out);
	assert(outfile.is_open());
	outfile << result;
	outfile.close();

	return 0;
}

 

输入文件:

最大间隙问题-鸽舍原理_第1张图片

输出文件:

最大间隙问题-鸽舍原理_第2张图片

 

参考地址:

http://nfeng.cc/2016/03/15/maximum-gap-problem/

https://blog.csdn.net/sky123bird/article/details/18845001

 

你可能感兴趣的:(算法分析设计)