最大间隙问题 给定 n 个实数,求这n个实数在数轴上相邻2个数之间的最大差值,设计解最大间隙问题的线性时间算法
分析:
最直接的方法是接收n个输入的实数后,排序(从小到大或者从大到小都可以),再计算它们之间的间隙,找出最大的间隙。但是因为有排序,就不满足线性时间算法。
可以用鸽笼原理(也叫做抽屉原理)解决
步骤:
1、接收输入的实数,找出最大值和最小值
2、max和min可以通过遍历得知,把min到max之间的间隙等分,分成n-1个区间,每个区间都是大小相等的。那么,min属于第一个区间,max属于最后一个区间。并且第i个区间的上限是第i+1个区间的下限。每个区间的大小为gap=(max-min)/(n-1)
3、把除去max和min的另外n-2个数放到n-1个区间里。numOfBucket是每个实数所属的区间号,count数组中对应的那个值加1,证明该区间拥有至少一个实数。把low[i]设置成max,把high[i]设置成min,是为了便于后面的判断
4、最后判断最大的间隙时,如果一个区间内有两个或者以上的实数,那么它们之间的间隙肯定不是最大的,因为这些数都挤到一块了。相反,跨区间的数才可能产生最大的间隙
#include<stdio.h>
int main(){
int n,i;
scanf("%d",&n);//输入实数的个数
float*number=new float[n];
//接收n个实数
for(i=0;i<n;i++){
scanf("%f",&number[i]);
}
//找出其中的最大值和最小值
float max,min;
int maxIndex,minIndex;
max=min=number[0];
maxIndex=minIndex=0;
for(i=0;i<n;i++){
if(max<number[i]){
max=number[i];
maxIndex=i;
}
if(min>number[i]){
min=number[i];
minIndex=i;
}
}
//把除去max和min的另外n-2个数放到n-1个区间里
int*count=new int[n-1];
float*high=new float[n-1];
float*low=new float[n-1];
float gap=(max-min)/(n-1);
for(i=0;i<n-1;i++)
{
count[i]=0;
high[i]=min;
low[i]=max;
}
for(i=0;i<n-1;i++){
int numOfBucket=(int)((number[i]-min)/gap);
count[numOfBucket]++;
if(number[i]<low[numOfBucket]){
low[numOfBucket]=number[i];
}
if(number[i]>high[numOfBucket]){
high[numOfBucket]=number[i];
}
}
//第一个区间里面肯定有数,最起码min在里面
float temp=0;
float left=high[0]; //第一个桶里肯定有数
//输出最大的间距
for(i=1;i<n-1;i++)
{
if(count[i])
{
if(low[i]-left>temp)
temp=low[i]-left;
left=high[i];
}
}
printf("%.2f\n",temp);
return 0;
}