问题

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

时间复杂度:O(n)

  • 算法基于桶排序
  • 鸽舍原理(在同一个区间内不会存在最大差值)
  • 对桶排序进行改良(只记录桶内的最大最小值)

代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define mmax 1000 //该值随意
#define mmin 0    //该值随意

int main()
{
    //参数变量
    int n, i, bucket;
    double maxValue = mmin, minValue = mmax, begin, maxgap = 0.0, temp;

    //数组个数
    scanf("%d", &n);

    double* num = new double[n];//存放数据的数组

    //定义Bucket
    int* count = new int[n]; //计数
    double* maxNum = new double[n];//桶内的最大值
    double* minNum = new double[n];//桶内的最小值

    //找出最大值最小值
    for (i = 0; i < n; i++) {
        scanf("%lf", &num[i]);

        if (num[i] > maxValue)
            maxValue = num[i];

        if (num[i] < minValue)
            minValue = num[i];
    }

    //初始化桶
    for (int i = 0; i < n; i++) {
        count[i] = 0;
        maxNum[i] = minValue;
        minNum[i] = maxValue;
    }

    //桶排序
    for (i = 0; i < n; i++) {
        //计算该值所在的区间(桶)
        bucket = (int)((num[i] - minValue) / ((maxValue - minValue) / (n - 1)));
        count[bucket]++;//当前桶计数+1
        if (maxNum[bucket] < num[i])//当前桶内的最大值
            maxNum[bucket] = num[i];
        if (minNum[bucket] > num[i])//当前桶内的最小值
            minNum[bucket] = num[i];

    }

    //前提:鸽舍原理可知 最大差值不会出现在同一个区间内(桶)

    //初始值比较值
    begin = maxNum[0];

    //开始便利查找桶之间的最大差值
    for (i = 1; i < n; i++) {
        if (count[i]) {//桶中的元素不为空则查找

            //计算相邻两个桶"区间边"上的差值(即第i个区间的最大值和第i+1区间的最小值的差值)
            //因为第i个区间(桶)的最大值一定比第i+1个区间的最小值还小
            temp = minNum[i] - begin;
            if (temp > maxgap)//不断遍历所有桶查找比较找出最差大值的值
                maxgap = temp;
            begin = maxNum[i];//当查找到最大差值时将当前桶中最大值最为下一次比较的初始值;
        }
    }
    printf("%.2f\n", maxgap);
    return 0;
}

样例

  • 对于100%的数据,1≤ n ≤5×10^4, 0≤ xi ≤10^5

输入

  • 第一行输入一个正整数n。 第二行输入n个实数,小数位数为两位。各个实数之间用空格隔开

    7
    79.34 20.30 54.98 39.56 95.46 27.14 23.54

输出

  • 最大间隙,保留两位有效小数
24.36
最后修改:2022 年 09 月 19 日
如果觉得我的文章对你有用,请随意赞赏