求解思路说明
本题输入的实数序列中存在最大值和最小值(设为left和right),在数轴上分别作为本题输入的所有实数的右边界和左边界,作为一个区间。
设输入的实数个数为n,则该区间被这些实数分为n-1段。若将该区间平分为n-1段,则每段长度为
len=(right-left)/(n-1)
。根据鸽笼原理可知,相邻两个实数之间的最大差值(距离)
l≥len
。因此该相邻的两个实数在等分出的n-1段区间中一定位于两个不同的区间或都为区间端点,且其中较小数和较大数分别为各自所在等分区间所输入的实数中的最大值和最小值。因此,统计相邻等分区间之间较大区间中的最小实数值和较小区间中的较大实数值的差值,该最大差值即为这n个实数在数轴上相邻2个数之间的最大差值。
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef long long ll;
#define MAX 0x7fffffff
ll n;
double maxInterval=-MAX;
double findMax(double *a,ll n)
{
double m=-MAX;
for(ll i=0;i<n;++i)
{
if(a[i]>m)
{
m=a[i];
}
}
return m;
}// 找到最大值
double findMin(double *a,ll n)
{
double m=MAX;
for(ll i=0;i<n;++i)
{
if(a[i]<m)
{
m=a[i];
}
}
return m;
}// 找到最小值
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%lld",&n);
double *a=(double *)malloc(n*sizeof(double));// 存放输入的实数
for(ll i=0;i<n;++i)
{
scanf("%lf",&a[i]);
}
double left=findMin(a,n);
double right=findMax(a,n);// 最大最小左右边界
double *high=(double *)malloc((n-1)*sizeof(double));
double *low=(double *)malloc((n-1)*sizeof(double));// 存放每个等分区间的最大最小数
for(ll i=0;i<n-1;++i)
{
high[i]=left;
low[i]=right;
}
for(ll i=0;i<n;++i)
{
ll num=(ll)((n-1)*((a[i]-left)/(right-left)));
if(num>=n-1)
{
num-=1;
}
if(a[i]>high[num])
{
high[num]=a[i];
}
if(a[i]<low[num])
{
low[num]=a[i];
}
}// 扫描所有实数,更新每个等分区间中的最大最小值
if(n==2)
{
printf("%lf\n",high[0]-low[0]);
return 0;
}
for(ll i=0;i<n-2;++i)
{
if(i>0&&high[i]==left)
{
continue;
}
ll j;
for(j=i+1;j<n-2&&low[j]==right;++j){}
if(low[j]-high[i]>maxInterval)
{
maxInterval=low[j]-high[i];
}
}//计算并统计最大间隙
printf("%lf\n",maxInterval);
return 0;
}
算法运行截屏
输入数据文件input.txt:
算法运行过程中截图:
输出数据文件output.txt: