最大间隙问题(鸽笼)

问题描述:

给定n个实数,求n个实数在数轴上相邻两个数之间的最大差值,设计解最大间隙问题的线性时间算法。

在这里插入图片描述

算法思想:

方法一:如果先排序,再求最大间隙值。最好的排序方法时间复杂度为O(nlogn),题目要求线性时间,不符合要求。
方法二:鸽笼原理。百度:桌上有十个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面放不少于两个苹果。这一现象就是我们所说的“抽屉原理”。 抽屉原理的一般含义为:“如果每个抽屉代表一个集合,每一个苹果就可以代表一个元素,假如有n+1个元素放到n个集合中去,其中必定有一个集合里至少有两个元素。” 抽屉原理有时也被称为鸽巢原理。

  • 我们把五个数放在四个集合中,必定有一个集合至少有两个元素,每个集合中有最大值smax和最小值smin。
  • 如果有一个集合为空,那最大间隙为后一个集合的最小值—前一个集合的最大值。
    最大间隙问题(鸽笼)_第1张图片
#include 
#define N 100
struct node
{
	int sum;//每段有sum个数
	float smax,smin;//每段的最大值、最小值
};
struct node v[N];//每个段组成的数组

int main()
{
	int n,m,i;
	float a[N],x;
	float max = 0;
	float min =1000;
	scanf("%d",&n);//数据个数

	for(i = 0;i < n;i++)
	{
		scanf("%f",&a[i]);
		if(a[i] > max)
			max = a[i];//数据最大值
		if(a[i] < min)
			min = a[i];//数据最小值
	}

	float len = (max - min)/(n - 1);//每段大小
	for(i = 1;i < n;i++)//初始化每段
	{
		v[i].smax = v[i].sum = 0;
		v[i].smin = 1000;
	}
	v[1].smin = min;
	v[n-1].smax = max;
	v[1].sum = v[n-1].sum = 1;

    for(i = 0;i < n;i++)
	{
		m = (a[i] - min)/len + 1;//a[i]放在第几段上
		if(m == n)//处理数据的最大值
			v[m -1].sum++;
		else v[m].sum++;
		if(a[i] > v[m].smax )
			v[m].smax = a[i];
		if(a[i] < v[m].smin )
			v[m].smin = a[i];
	}
	for(i = 1;i < n;i++)
	 {
		 if(v[i].sum == 0)
		 x = v[i + 1].smin - v[i - 1].smax;
	 }
	 printf("%.1f\n",x);
     return 0;
}

运算结果:最大间隙问题(鸽笼)_第2张图片

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