给定n个实数x1,x2,...,xn,求这n个实数在实轴上相邻2个数之间的最大差值M,要求设计线性的时间算法

来源:互联网 发布:linux socket udp 编辑:程序博客网 时间:2024/04/28 05:15

 最大间隙问题。

要求线性时间算法。需要使用桶排序。桶排序的平均时间复发度是O(N).如果桶排序的数据分布不均匀,假设都分配到同一个桶中,最坏情况下的时间复杂度将变为O(N^2).

以下引用其他人的算法详解及一些个人理解。

桶排序: 最关键的建桶,如果桶设计得不好的话桶排序是几乎没有作用的。通常情况下,上下界有两种取法,第一种是取一个10^n或者是2^n的数,方便实现。另一种是取数列的最大值和最小值然后均分作桶。

对于这个题,最关键的一步是:由抽屉原理知:最大差值M>= (Max(V[n])-Min(V[n]))/(n-1)!
所以,假如以(Max(V[n])-Min(V[n]))/(n-1)为桶宽的话,答案一定不是属于同一个桶的两元素之差。因此,这样建桶,每次只保留桶里面的最大值和最小值即可。


 个人理解 :若以offset = (Max(V[n])-Min(V[n]))/(n-1)平均距离作为桶宽的话,要N个实数放置到各个对应的桶中。需要计算出每个实数对应桶的坐标。且每个桶中可能会有多个实数,根据

上述的原理,只需要在每个桶中记录最大值和最小值即可。而坐标如何计算呢。我们知道每个桶的宽度是(Max(V[n])-Min(V[n]))/(n-1),所以,每个实数与最小值之差(肯定是坐落在(Max(V[n])-Min(V[n]))之间的)除以 每个桶的宽度即为坐标。

 

算法:
  距离平均值为offset = (arrayMax - arrayMin) / (n - 1), 则距离最大的数必然大于这个值
  每个桶只要记住桶中的最大值和最小值,依次比较上一个桶的最大值与下一个桶的最小值的差值
  找最大的即可.

 

#include <iostream>
#define MAXSIZE 100    //实数的个数
#define MAXNUM 32767
using namespace std;
struct Barrel
{
 double min;   //桶中最小的数
 double max;   //桶中最大的数
 bool flag;   //标记桶中有数
};
int BarrelOperation(double* array, int n)
{
 Barrel barrel[MAXSIZE];  //实际使用的桶
 int nBarrel = 0;  //实际使用桶的个数
 Barrel tmp[MAXSIZE];   //临时桶,用于暂存数据
 double arrayMax = -MAXNUM, arrayMin = MAXNUM;
 for(int 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);  //所有数的平均间隔
 //对桶进行初始化
 for(i = 0; i < n; i++) { 
  tmp[i].flag = false;
  tmp[i].max = arrayMin;
  tmp[i].min = arrayMax;
 }
 //对数据进行分桶
 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];
  } 
 }
 for(i = 0; i <= n; i++) {
  if(tmp[i].flag)
   barrel[nBarrel++] = tmp[i];   
 }
 int 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;
}
int main()
{
 double array[MAXSIZE] = {1, 8, 6, 11, 7, 13, 16, 5};  //所需处理的数据
 int n = 8; //数的个数
 //double array[MAXSIZE] = {8, 6, 11};
 //int n = 3;
 int maxOffset = BarrelOperation(array, n);
 cout << maxOffset << endl;
 return 0;
}

 

原创粉丝点击