文章标题

问题描述

最大间隙问题:给定n个实数x1,x2,…,xn,求这n个实数 在实轴上相邻2个数之间的最大差值(线性时间)。

算法思路

  1. 找到n个数据中最大和最小数据max和min;
  2. 用n-2个点等分区间[min,max],即将[min,max]等分为n-1个区间(前闭后开区间),将这些区间看做桶,桶的结构体分为max,min和flag,分别表
    示桶里的最大、最小和是否是空桶,编号为1,2,…,n-2,n-1,且桶i的上界和桶i+1的下界相同,即每个桶的大小相同,每个大小为: offset=(maxmin)/(
    n-1);
  3. 将n个数放入n-1个桶中:按如下规则将x[i]分配到某个桶(编号pos)中: pos = int((array[i] - min)/offset);
  4. 求最大间隙:除最大最小数据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();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值