最大间隙问题(线性时间)

问题描述:
最大间隙问题:给定n 个实数x1, x2 ,..., xn,求这n 个数在实轴上相邻2 个数之间的最大差值。假设对任何实数的下取整函数耗O(1),设计解最大间隙问题的线性时间算法。

编程任务:
对于给定的n 个实数x1,x2,...,xn,编程计算它们的最大间隙。

数据输入:
输入数据由文件名为input.txt的文本文件提供。文件的第1 行有1 个正整数n。接下来的1 行中有n个实数 x1,x2,...,xn 。

结果输出:

程序运行结束时,将找到的最大间隙输出到文件output.txt中。
输入文件示例 输出文件示例
input.txt
5
2.3 3.1 7.5 1.5 6.3

output.txt

3.2

思路:
因为不能用排序(排序算法最小时间复杂度为O(nlogn)),可以先取这组数的最大值max和最小值min,然后将这段区间分为n-1个,区间上界为max,下界为min,这样就可以将n-2个数放到n-1个区间中,根据鸽巢原理,至少有一个区间中没有数,放完数后再从头开始扫,找出最大间隙,,,


#include<stdio.h>
#define MIN -10000000
#define MAX 10000000
double block_max[1000];             //存放每个区间的最大值
double block_min[1000];           //存放每个区间的最小值
int block_count[1000];             //记录区间中的数的个数
int n;
double max_gap=MIN;
double a[1000];
void init()
{                                                    //初始化数组
    int i;
    for(i=0;i<n;i++)
    {
        block_max[i]=MIN;
        block_min[i]=MAX;
        block_count[i]=0;
    }
}
int main()
{
   double min,max;
    int i,j,index;
    double gap;
   min=MAX;
     max=MIN;
    scanf("%d",&n);
    init();
    for(i=0;i<n;i++)
    {                                                        //找出这组数中的最大数和最小数
        scanf("%lf",&a[i]);
        if(a[i]<min)
            min=a[i];
        if(a[i]>max)
            max=a[i];
    }
    //printf("%.2lf %.2lf\n\n",min,max);     
    gap=(max-min)/(n-1);                                 //每个区间的初始大小
    for(i=0;i<n;i++)
    {
        index=(int)((a[i]-min)/gap);
        if(index==n-1)
            index--;
        if(block_max[index]<a[i])                              //改变区间的上界
            block_max[index]=a[i];
        if(block_min[index]>a[i])                             //改变区间的下界
            block_min[index]=a[i];
        block_count[index]++;
    }
  
    i=0;
    double gap_left,gap_right;
    int flag;
    while(i<n-1)
    {                                                                 //从头开始扫
        if(block_count[i]>0)
        {                                                   
            gap_left=block_max[i];                        //若区间中有数,记录区间的最大值
             flag=i+1;                                              //接着往后扫
            while(flag<n-1)
            {
                if(block_count[flag]>0)             //发现区间中有数,记录区间的最小值
                {
                     gap_right=block_min[flag];
                    break;
                }
                flag++;
            }
        }
        double re_gap=gap_right-gap_left;            //计算两个数的间隙
        if(re_gap>max_gap)
        {
            max_gap=re_gap;
        }
        i=flag;                                          //从当前位置开始扫
    }
    printf("%.2lf\n",max_gap);
    return 0;
}

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值