最大间距问题(元素分段/分桶法)



最大间隙问题:(元素分段法/分桶法(bucket)

(一)问题:
已知一个整数数组a[n],找出n个元素在数轴上两个相邻元素之间的最大间距。

(二)解析:

(1)方案一:
先对n个数据排序,然后扫描一遍可以找到有序数组中相邻元素的最大间距。
( 时间复杂度为O(n*lgn) )

(2)方案二:O(n)

1.扫描一遍数组,找到数组中的最大值max,最小值min.(时间复杂度为O(n))
2.将[min,max]区间分为n-1份区域,则每一个区域的大小为len=(max-min)/(n-1);区间分别为:[min,min+len),[min+len,min+2*len),[min+2*len,min+3*len),...[max-len,max].
3.最大间距=相邻的两个区间 or 不相邻的两个区间,但中间区间没有元素 且 是前一个区间的最大值与后一个区间的最小值之间产生。
4.求出每个区间的最大值,以及最小值,然后扫描一遍就能求出最大间距。

(三)代码实现:

#define MAXINT (1<<31)-1
#define MININT 1<<31
typedef struct _bucket
{
    int min, max;
} Bucket;

/*求取数组a[n]在数轴上的相邻两个元素的最大间距*/
int maxGap(int *a, int n)
{
    int max = MININT, min = MAXINT, i;
    double bucketLen;
    //扫描一遍数组,得到最大值max,最小值min.复杂度为O(n)
    for(i = 0; i < n; ++i)
    {
        if(a[i] > max) max = a[i];
        if(a[i] < min) min = a[i];
    }
    bucketLen = (max-min) * 1.0 / (n-1);//桶的大小,即每段区域的大小
    Bucket *bucket = new Bucket[n-1];//开辟n-1段区域。

    //初始化每段区域的最大,最小值,即初始化每段区域为空 。
    for(i = 0; i < n-1; ++i)
    {
        bucket[i].max = MININT;
        bucket[i].min = MAXINT;
       
    }
    //初始化第一个区域的最大,最小值为min,
    //初始化第n-1个区域的最大,最小值为max.
    bucket[0].max = min; bucket[0].min = min;
    bucket[n-2].max = max; bucket[n-2].min = max;

    //将数组中的其他n-2个数,放到n-1个区域中。并且获得每个区域的最大,最小值。复杂度为O(n)
    for(i = 0; i < n; ++i)
    {
        int index;
        if(a[i] != min && a[i] != max)
        {
            index = (a[i]-min) * 1.0 / bucketLen;
            //获取当前元素坐在区域的区域号。区域号从0~n-2;

            if(bucket[index].max < a[i]) bucket[index].max = a[i];
            if(bucket[index].min > a[i]) bucket[index].min = a[i];
        }
    }

//最大间距在两个相邻区域出现,或者两个不相邻的区域出现且中间区域为空,
//最大间距一定是前一个区域的最大值与后一个区域的最小值之间出现。

    int low = -1, high = -1, maxGap = 0, curGap, pre = 0;
//low记录的是最大间距的前一个数,high记录的是最大区间的后一个数。
//maxGap为最大间距,pre为最大间距出现的两个区域中的前一个区域的编号。

    for(i = 1; i < n-1; ++i)
    {
        if(bucket[i].max != MAXINT)//区域i非空
        {
            curGap = bucket[i].min - bucket[pre].max;
            if(curGap > maxGap)
            {
                maxGap = curGap;
                low = bucket[pre].max, high = bucket[i].min;
            }
            pre = i;
        }
    }
    printf("the maximum gap is %d, between %d and %d!\n", maxGap, low, high);
    return maxGap;
}

int main()
{
    int a[] = {1,8,4,5,6};
    maxGap(a,5);
    return 0;
}

你可能感兴趣的:(数据结构与算法)