问题描述:
给定n个实数,求n个实数在数轴上相邻两个数之间的最大差值,设计解最大间隙问题的线性时间算法。
算法思想:
方法一:如果先排序,再求最大间隙值。最好的排序方法时间复杂度为O(nlogn),题目要求线性时间,不符合要求。
方法二:鸽笼原理。百度:桌上有十个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面放不少于两个苹果。这一现象就是我们所说的“抽屉原理”。 抽屉原理的一般含义为:“如果每个抽屉代表一个集合,每一个苹果就可以代表一个元素,假如有n+1个元素放到n个集合中去,其中必定有一个集合里至少有两个元素。” 抽屉原理有时也被称为鸽巢原理。
- 我们把五个数放在四个集合中,必定有一个集合至少有两个元素,每个集合中有最大值smax和最小值smin。
- 如果有一个集合为空,那最大间隙为后一个集合的最小值—前一个集合的最大值。
#include <stdio.h>
#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;
}