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

源:http://blog.csdn.net/livelylittlefish/archive/2008/03/23/2209537.aspx

最大间隙问题

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

算法思想:

                              
                            
咋看这个题目,最先想到的方法就是先对n个数据进行排序,然后一边扫描即可确定相邻的最大间隙。但该方法不能满足线性时间的要求。故采取如下方法:
                                                  
1. 找到n个数据中最大和最小数据maxx和minx;
                                        
2. 用n-2个点等分区间[minx,maxx],即将[minx,maxx]等分为n-1个区间(前闭后开区间),将这些区间看做桶,编号为1,2,...,n-2,n-1,且桶i的上界和桶i+1的下届相同,即每个桶的大小相同;
    每个桶的大小为: dblAvrGap=(maxx-minx)/(n-1)
    实际上,这些桶的边界就构成了一个等差数列(首项为minx,公差d=dblAvrGap),且人为将minx放入第1个桶,将maxx放入第n-1个桶。
                                
    编程实现中,用以下数据结果存放有关桶的数据:
            int *count=new int[n];  //实际分到每个桶的数据个数
            double *low=new double[n]; //实际分到每个桶的最小数据
            double *high=new double[n]; //实际分到每个桶的最大数据
                            
3. 将n个数放入n-1个桶中:
     3.1 按如下规则将x[i]分配到某个桶(编号index)中:  index=int((x[i]-minx)/dblAvrGap)+1;

                若x[i]=minx,则被分到第1个桶中(minx即为桶1的下界);
                若x[i]=桶j的下界(也是桶j-1的上界),则被分到桶j中(j>=1);
                若x[i]=maxx,则被分到桶n中(max为桶n的下界桶n-1的上界),但没有桶n,解决办法:
                        可人为将其移入桶n-1中或者再加一个桶,这并不影响求其最大间隙;
                                           
      3.2 调整分到该桶的最大最小数据;
                                                                
4. 求最大间隙:
      除最大最小数据maxx和minx以外的n-2个数据被放入n-1个桶中,由抽屉原理可知至少有一个桶是空的;
      又因每个桶的大小相同,所以最大间隙不会在同一桶中出现;
      一定是某个桶的上界(dblHigh)和其后某个桶的下界(dblLow)之间隙,且该两桶之间的桶(即编号在该两桶编号之间的桶)一定是空桶;
      即最大间隙在桶i的上界和桶j的下界之间产生(j>=i+1);
                                

                                    
代码如下:  

                          
                           
输入:
            文件格式:
            n
            x1 x2 ... xn
输出:maxgap(最大间隙)
                              
/* ***********************************************************************
 * 最大间隙问题:给定n个实数x1,x2,...,xn,求这n个实数在实轴上相邻2个数之间
 *   的最大差值,要求设计线性的时间算法
 ***********************************************************************
*/


#include
< iostream >
#define  FILENAMELENGTH 50

// 声明函数
template < class  T >
int  indexofmin( int  n,T  * x);

template
< class  T >
int  indexofmax( int  n,T  * x);

//
class  CMaxGap
{
public :

    
int  m_nCount;         // 数据的个数
     double  m_dblMaxGap;     // 最大间隙
     double   * m_dblNumber; // 存放数据的数组

    CMaxGap(
const   char   * filename);
    
~ CMaxGap();

    
double  GetMaxGap( int  n, double   * x);
    
void  Display();
}
;

// 读入数据
CMaxGap::CMaxGap( const   char   * filename)
{
    FILE 
* fp = fopen(filename, " r " );
    
if (fp == NULL)
    
{
        printf(
" can not open file! " );
        exit(
0 );
    }


    
// 读入数据个数
    fscanf(fp, " %d " , & m_nCount);

    m_dblNumber
= new   double [m_nCount];
    
// 读入每个具体的数据
     for ( int  i = 0 ;i < m_nCount;i ++ )
        fscanf(fp,
" %lf " , & m_dblNumber[i]);

    m_dblMaxGap
= 0 ;
    fclose(fp);
}


CMaxGap::
~ CMaxGap()
{
    delete[] m_dblNumber;
    m_dblNumber
= NULL;
}


// 获取n个数据的最大间隙,存放在以x为开始地址的单元中,数据下标为0,1,...,n-1
double  CMaxGap::GetMaxGap( int  n, double   * x)
{
    
// 找到最大最小数据,考虑到浮点型数据在传递过程中可能会有微小的变化
    
// 故采取取其下标的方式,在直接读取
     int  minindex = indexofmin(n,x);
    
int  maxindex = indexofmax(n,x);
    
double  minx = x[minindex];
    
double  maxx = x[maxindex];

    
// 用n-2个点等分区间[minx,maxx],产生n-1个桶,桶编号1,2,...,n-2,n-1
    
// 且桶i的上界和桶i+1的下届相同
     double  dblAvrGap = (maxx - minx) / (n - 1 );     // 每个等分区间大小,即每个桶的大小
     int   * count = new   int [n];         // 实际分到每个桶的数据个数
     double   * low = new   double [n];     // 实际分到每个桶的最小数据
     double   * high = new   double [n];     // 实际分到每个桶的最大数据

    
// 初始化桶
     for ( int  i = 0 ;i < n;i ++ )
    
{
        count[i]
= 0 ;
        low[i]
= maxx;
        high[i]
= minx;
    }


    
int  index;     // 桶编号
    
// 将n个数放入n-1个桶中
     for ( int  i = 0 ;i < n;i ++ )
    
{
        
// 按如下规则将x[i]分配到某个桶(编号index)中
        
// 若x[i]=minx,则被分到第1个桶中(minx即为桶1的下界)
        
// 若x[i]=桶j的下界(也是桶j-1的上界),则按如下公式被分到桶j中(j>=1)
        index = int ((x[i] - minx) / dblAvrGap) + 1 ;

        
// 若x[i]=maxx,则被分到桶n中(max为桶n的下界桶n-1的上界)
        
//     但没有桶n,此时可人为将其移入桶n-1中,或者再加一个桶
        
// 该步操作不影响下面的求最大间隙
         if (index == n)
            index
-- ;

        count[index]
++ ;    
        
// 调整分到该桶的最大最小数据
         if (x[i] < low[index])
            low[index]
= x[i];
        
if (x[i] > high[index])
            high[index]
= x[i];
    }


    
// 除最大最小数据maxx和minx以外的n-2个数据被放入n-1个桶中
    
//   由抽屉原理可知至少有一个桶是空的
    
// 又因每个桶的大小相同,所以最大间隙不会在同一桶中出现
    
//   一定是某个桶的上界(dblHigh)和其后某个桶的下界(dblLow)之间隙
    
//       注意:该两桶之间的桶(即编号在该两桶编号之间的桶)一定是空桶
    
//   即最大间隙在桶i的上界和桶j的下界之间产生(j>=i+1)
     double  dblMaxGap = 0 ,dblHigh = high[ 1 ],dblTempGap;
    
for ( int  i = 2 ;i < n;i ++ )
    
{
        
if (count[i])     // 该桶非空才计算
         {
            dblTempGap
= low[i] - dblHigh;
            
if (dblMaxGap < dblTempGap)
                dblMaxGap
= dblTempGap;
            dblHigh
= high[i];
        }

    }


    
// 释放
    delete[] count;
    count
= NULL;
    delete[] low;
    low
= NULL;
    delete[] high;
    high
= NULL;

    m_dblMaxGap
= dblMaxGap;
    
return  dblMaxGap;
}


void  CMaxGap::Display()
{
    printf(
"   %d numbers:    " ,m_nCount);
    
for ( int  i = 0 ;i < m_nCount;i ++ )
    
{
        printf(
" %.2f  " ,m_dblNumber[i]);
    }

    printf(
"   the max gap is: %.2f " ,m_dblMaxGap);
}


// 求数组中最小数据的下标
template < class  T >
int  indexofmin( int  n,T  * x)
{
    
int  index;
    T temp
= x[ 0 ];
    
for ( int  i = 1 ;i < n;i ++ )
    
{
        
if (x[i] < temp)
        
{
            temp
= x[i];
            index
= i;
        }

    }

    
return  index;
}


// 求数组中最大数据的下标
template < class  T >
int  indexofmax( int  n,T  * x)
{
    
int  index;
    T temp
= x[ 0 ];
    
for ( int  i = 1 ;i < n;i ++ )
    
{
        
if (x[i] > temp)
        
{
            temp
= x[i];
            index
= i;
        }

    }

    
return  index;
}


// 显示菜单
void  show_menu()
{
    printf(
" --------------------------------------------- " );
    printf(
" input command to test the program " );
    printf(
"    i or I : input filename to test " );
    printf(
"    q or Q : quit " );
    printf(
" --------------------------------------------- " );
    printf(
" $ input command > " );
}


void  main()
{
    
char  sinput[ 10 ];
    
char  sfilename[FILENAMELENGTH];

    show_menu();

    scanf(
" %s " ,sinput);
    
while (stricmp(sinput, " q " ) != 0 )
    
{
        
if (stricmp(sinput, " i " ) == 0 )
        
{
            printf(
"   please input a filename: " );
            scanf(
" %s " ,sfilename);

            
// 求文件中数据的最大间隙
            CMaxGap gap(sfilename);
            
double  dblMaxGap = gap.GetMaxGap(gap.m_nCount,gap.m_dblNumber);
            gap.Display();
        }


        
// 输入命令
        printf( " $ input command > " );
        scanf(
" %s " ,sinput);
    }

}
                                               
                                            

运行结果如下:

                                    
                              
test.txt:
5
2.3 3.1 7.5 1.5 6.3
                             
程序运行后count,low和high数组的值如下:
index01234
count02102
low7.51.53.17.56.3
high1.52.33.11.57.5
 
 
 
 
 
 
                                   
                                   
test1.txt:
5
2.3 3.0 7.5 1.5 6.3
                                    
程序运行后count,low和high数组的值如下:
index01234
count02102
low7.51.53.07.56.3
high1.52.33.01.57.5
 
 
 
 
 
 
                                     
                                        
test2.txt:
5
4.5 3.0 7.5 1.5 6.0
                       
程序运行后count,low和high数组的值如下:
index01234
count01112
low7.51.53.04.56.0
high1.51.53.04.57.5
 
 
 
 
 
 
                                   
                                             
test3.txt:
5
2.3 3.1 10.0 1.5 6.3
                                         
程序运行后count,low和high数组的值如下:
index01234
count03011
low10.01.510.06.310.0
high1.53.13.06.310.0
 
 
 
 
 
 
                                                                         
                                                
test.4.txt:
15
2.3 3.1 10.0 1.5 6.3 10.2 1.0 25.3 3.4 6.5 21.4 18.3 11.7 24.1 19.9
                                                    
程序运行后count,low和high数组的值如下:
index01234567891011121314
count032020210011102
low25.31.03.125.36.325.310.011.725.325.318.319.921.425.324.1
high1.02.33.41.06.51.010.211.71.01.018.319.921.41.025.3
 
 
 
 
 
 
                                                             
                                                

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值