鸽舍原理求最大间隙

鸽舍原理:也称"抽屉原理"或利克雷原则,它是一个重要而又基本的数学原理,应用它可以解决各种有趣的问题,并且常常能够得到令人惊奇的结果,许多看起来相当复杂,甚至无从下手的问题,利用它能很容易得到解决。
原理1:把n+1个元素分成n类,不管怎么分,则一定有一类中有2个或2个以上的元素。
原理2:把多于m×n个物体放到n个抽屉里,那么一定有一个抽屉里有m+1个或者m+1个以 上的物体。
原理2-1:把m个元素任意放入n(n<=m)个元素,则一定有一个集合至少有k个元素。 其中 k= [m/n]([]表示向上取整)。
(抽屉原理的一般含义为:"如果每个抽屉代表一个集合,每一个苹果就可以代表一个元素,假如有 n+1或多于n+1个元素放到n个集合中去,其中必定至少有一个集合里至少有两个元素。" ) 
                                                                                                                                                                    ----- http://baike.baidu.com/view/9738418.htm
 
鸽舍原理求最大间隙:
问题描术:
最大间隙问题:给定n个实数x1,x2,……,xn,求这n个数在实轴上相邻2个数之间的最大差值。假设对任何实数的下取整方法耗时为O(1),设计解最大间隙问题的线性时间算法。
编程任务:
对于给定的n个实数x1,x2,……,xn。编程计算它们的最大间隙。
输入:
5
2.3  3.1  7.5  1.5  6.3
输出:
3.2
 
代码如下:
 
#include
#include
#include
#include
#include
#include    //for memset()
#include     //for floor()
 
#define _Print_ 0
 
using namespace std;
 
//打开文件,将数据保存到vector类型的vec中
template
int readfile(string filename, vector &vec)
{
  ifstream ifile(filename.c_str(), ios_base::binary | ios_base::in);
  if (!ifile)
  {
    cerr << "cannot open file!\n";
    exit(1);
  }
  string str("");
  getline(ifile, str);//第一行数据总个数,也可以直接统计vec长度
  str = "";
  while (getline(ifile, str))
  {
    size_t pos = 0;
    size_t pos2 = 0;
    while (pos2 <= str.size())
    {
      pos = str.find(' ', pos2);
      if (pos != -1)
      {
        vec.push_back(atof(str.substr(pos2, pos - pos2).c_str()));
        pos2 = ++pos;
      }
      else
      {
        vec.push_back(atof(str.substr(pos2).c_str()));
        break;
             
    }
  }
 
  return vec.size();
}
 
//打印vector模板中的元素
template
inline void printvec(vector &vec)
{
  for (auto it = vec.begin(); it != vec.end(); ++it)
  {
    std::cout << *(it) << std::ends;
  }
  std::cout << std::endl;
}
 
 
//找到vector中最小值对应的下标
template
inline int getMinIndex(vector &vec)
{
  int min_index = 0;
  for (size_t index = 1; index < vec.size(); ++index)
  {
    if (vec[index] < vec[min_index])
    {
      min_index = index;
    }
  }
  return min_index;
}
 
//找到vector中最大值对应的下标
template
inline int getMaxIndex(vector &vec)
{
  int max_index = 0;
  for (size_t index = 1; index < vec.size(); ++index)
  {
    if (vec[index] > vec[max_index])
    {
      max_index = index;
    }
  }
  return max_index;
}
 
//获得最大间隙
template
T getMaxGap(int n,vector &vec)
{
  typedef struct bucket
  {
    T low;
    T high;
    bool hasnum;
  }bucket;
 
  int max_index = getMaxIndex(vec);
  int min_index = getMinIndex(vec);
  T maxnum = vec[max_index];
  T minnum = vec[min_index];
  T buck_len = (maxnum - minnum)*1.0 / (n-1);
 
  bucket* buck = new bucket[n - 1];
  memset(buck, 0, (n - 1)*sizeof(bucket));
  int buck_num(0);
 
  //将n个元素每个元素放置到对应的桶内
  buck[0].low = minnum; buck[0].high = minnum; buck[0].hasnum = true;
  buck[n - 2].low = maxnum; buck[n - 2].high = maxnum; buck[n - 2].hasnum = true;
  for (int i = 0; i < n; ++i)
  {
    if ((min_index == i) || (max_index == i))
      continue;
    //先判定元素是属于哪一个桶的,再确认其是不是桶内的最大或者最小元素
    buck_num = floor((vec[i] - minnum) / buck_len);
    if (false == buck[buck_num].hasnum)
    {
      buck[buck_num].high = vec[i];
      buck[buck_num].low = vec[i];
      buck[buck_num].hasnum = true;
    }
    else
    {
      if (vec[i]>buck[buck_num].high)
      {
        buck[buck_num].high = vec[i];
      }
      else if (vec[i] < buck[buck_num].low)
      {
        buck[buck_num].low = vec[i];
      }
    }
  }
 
  //在n-1个桶的边界找到最大间隔
  T maxgap = 0;
  T curgap=0;
  int pre_index = 0;      //上一个非空的桶的位置
  for (int i = 1; i <= n - 2;++i)
  {
    if (buck[i].hasnum)
    {
      curgap = buck[i].low - buck[pre_index].high;
      if (curgap > maxgap)
      {
        maxgap = curgap;
      }
      pre_index = i;
    }
  }
 
  delete[] buck;
 
  return maxgap;
}
 
//将数据写入output文件
template
inline int writefile(string filename, T n)
{
  ofstream ofile(filename.c_str(), ios_base::binary | ios_base::out);
  if (!ofile)
  {
    cerr << "cannot open file!\n";
    exit(1);
  }
  ofile << n;
  cout << "write over." << endl;
  return 0;
}
 
int main()
{
  string ifilename , ofilename;
  vector vec;
  cout << "input filename and ofilename:\n";
  cin >> ifilename >> ofilename;
  int n = readfile(ifilename, vec);
  double maxgap = getMaxGap(n, vec);
  writefile(ofilename, maxgap);
 
#if _Print_
  {
    printvec(vec);
    cout << maxgap;
    system("pause");
  }
#endif
 
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值