问题描述
最大间隙问题:给定n个实数x1,x2,…,xn,求这n个实数 在实轴上相邻2个数之间的最大差值(线性时间)。
算法思路
- 找到n个数据中最大和最小数据max和min;
- 用n-2个点等分区间[min,max],即将[min,max]等分为n-1个区间(前闭后开区间),将这些区间看做桶,桶的结构体分为max,min和flag,分别表
示桶里的最大、最小和是否是空桶,编号为1,2,…,n-2,n-1,且桶i的上界和桶i+1的下界相同,即每个桶的大小相同,每个大小为: offset=(maxmin)/(
n-1); - 将n个数放入n-1个桶中:按如下规则将x[i]分配到某个桶(编号pos)中: pos = int((array[i] - min)/offset);
- 求最大间隙:除最大最小数据max和min以外的n-2个数据被放入n-1个桶中,因此至少有一个桶是空的,又因肯定有空桶存在,所以最大间隙不会
在同一桶中出现,而是在空桶两侧!又因求的是实数轴相邻两数的差值,因此和空桶两侧桶中间的数无关,即最大间隙在桶i的上界和桶j的下界之
间产生(j>=i+1)。为了遍历方便,将空桶删除,然后遍历一遍得到最大的间隔。
代码
C++
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Barrel
{
double min; //桶中最小的数
double max; //桶中最大的数
bool flag = false; //判断桶中是否有数据
};
double BarrelOperation(double * array, int n)
{
Barrel *barrel = new Barrel[n];
Barrel *tmp = new Barrel[n]; //临时桶
int i = 0;
double arrayMax = array[0], arrayMin = array[0];
//遍历一遍,求最大最小值
for (i = 0; i < n; i++){
if (array[i] >= arrayMax)
arrayMax = array[i];
if (array[i] <= arrayMin)
arrayMin = array[i];
}
double offset = (arrayMax - arrayMin) / (n - 1); //所有数的平均间隔,即桶的大小
//对桶进行初始化
tmp[0].min = arrayMin;
tmp[n - 2].max = arrayMax; //只有n-1个桶
//对数据进行分桶
for (i = 0; i < n ; i++){
int pos = (int)((array[i] - arrayMin) / offset); //数据对应的桶
if (!tmp[pos].flag){
tmp[pos].max = tmp[pos].min = array[i];
tmp[pos].flag = true;
}
else{
if (array[i] > tmp[pos].max){
tmp[pos].max = array[i];
}
if (array[i] < tmp[pos].min){
tmp[pos].min = array[i];
}
}
}
int nBarrel = 0; //实际使用桶的数目
for (i = 0; i < n; i++){
if (tmp[i].flag){
barrel[nBarrel++] = tmp[i];
}
}
double maxOffset = 0.0; //最大间隔
for (i = 0; i < nBarrel-1; i++){
if ((barrel[i + 1].min - barrel[i].max) > maxOffset)
maxOffset = barrel[i + 1].min - barrel[i].max;
}
return maxOffset;
}
void main()
{
int n ;
double *arrayNum;
//读入数据
FILE *fp = fopen("input.txt", "r");
if (fp == NULL)
printf("can not open file...");
//读入数据个数
fscanf(fp, "%d", &n); //facanf遇到空格和换行时结束
arrayNum = new double[n];
for (int i = 0; i < n; i++)
fscanf(fp, "%lf", &arrayNum[i]);
fclose(fp);
double maxOffset = BarrelOperation(arrayNum, n);
//结果输出
ofstream outfile;
outfile.open("output.txt");
outfile << maxOffset << endl;
outfile.close();
}