经典算法(3)——最大间隙问题(线性时间算法)
2008-03-23 13:24
555 查看
本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一、小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!
给定n个实数x1,x2,...,xn,求这n个实数在实轴上相邻2个数之间的最大差值,要求设计线性的时间算法
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
; //实际分到每个桶的数据个数
double *low=new double
; //实际分到每个桶的最小数据
double *high=new double
; //实际分到每个桶的最大数据
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
; //实际分到每个桶的数据个数
double *low=new double
; //实际分到每个桶的最小数据
double *high=new double
; //实际分到每个桶的最大数据
//初始化桶
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);
}
}
5
2.3 3.1 7.5 1.5 6.3
程序运行后count,low和high数组的值如下:
test1.txt:
5
2.3 3.0 7.5 1.5 6.3
程序运行后count,low和high数组的值如下:
test2.txt:
5
4.5 3.0 7.5 1.5 6.0
程序运行后count,low和high数组的值如下:
test3.txt:
5
2.3 3.1 10.0 1.5 6.3
程序运行后count,low和high数组的值如下:
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数组的值如下:
最大间隙问题
问题描述:给定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
; //实际分到每个桶的数据个数
double *low=new double
; //实际分到每个桶的最小数据
double *high=new double
; //实际分到每个桶的最大数据
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
; //实际分到每个桶的数据个数
double *low=new double
; //实际分到每个桶的最小数据
double *high=new double
; //实际分到每个桶的最大数据
//初始化桶
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数组的值如下:
index | 0 | 1 | 2 | 3 | 4 |
count | 0 | 2 | 1 | 0 | 2 |
low | 7.5 | 1.5 | 3.1 | 7.5 | 6.3 |
high | 1.5 | 2.3 | 3.1 | 1.5 | 7.5 |
5
2.3 3.0 7.5 1.5 6.3
程序运行后count,low和high数组的值如下:
index | 0 | 1 | 2 | 3 | 4 |
count | 0 | 2 | 1 | 0 | 2 |
low | 7.5 | 1.5 | 3.0 | 7.5 | 6.3 |
high | 1.5 | 2.3 | 3.0 | 1.5 | 7.5 |
5
4.5 3.0 7.5 1.5 6.0
程序运行后count,low和high数组的值如下:
index | 0 | 1 | 2 | 3 | 4 |
count | 0 | 1 | 1 | 1 | 2 |
low | 7.5 | 1.5 | 3.0 | 4.5 | 6.0 |
high | 1.5 | 1.5 | 3.0 | 4.5 | 7.5 |
5
2.3 3.1 10.0 1.5 6.3
程序运行后count,low和high数组的值如下:
index | 0 | 1 | 2 | 3 | 4 |
count | 0 | 3 | 0 | 1 | 1 |
low | 10.0 | 1.5 | 10.0 | 6.3 | 10.0 |
high | 1.5 | 3.1 | 3.0 | 6.3 | 10.0 |
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数组的值如下:
index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
count | 0 | 3 | 2 | 0 | 2 | 0 | 2 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 2 |
low | 25.3 | 1.0 | 3.1 | 25.3 | 6.3 | 25.3 | 10.0 | 11.7 | 25.3 | 25.3 | 18.3 | 19.9 | 21.4 | 25.3 | 24.1 |
high | 1.0 | 2.3 | 3.4 | 1.0 | 6.5 | 1.0 | 10.2 | 11.7 | 1.0 | 1.0 | 18.3 | 19.9 | 21.4 | 1.0 | 25.3 |
相关文章推荐
- 最大间隙问题(线性时间算法)
- 大数据面试题求解:给定n个实数 ,求着n个实数在实轴上向量2个数之间的最大差值,要求线性的时间算法(最大间隙问题)
- 最大间隙问题。给定 n 个实数,求这n个实数在数轴上相邻2个数之间的最大差值,设计解最大间隙问题的线性时间算法。
- 最大间隙问题(线性时间算法)
- 最大间隙问题 线性时间算法
- 最大间隙问题。给定 n 个实数,求这n个实数在数轴上相邻2个数之间的最大差值,设计解最大间隙问题的线性时间算法。
- 线性时间算法解决最大间隙问题
- 算法导论 4.1-5 最大子数组问题 线性时间算法 C++简单实现
- 算法导论-最大子数组问题-线性时间复杂度算法分析与实现
- 最大间隙问题(线性时间)
- 鸽舍原理 线性时间计算最大间隙问题
- 线性时间实现最大间隙问题
- 最大子数组问题---线性时间算法(转)
- 求解最大子序列和问题的线性时间算法
- C++解决最大子列和问题,算法时间复杂度优化
- 经典算法总结之线性时间做选择
- 算法探究:线性时间选择问题
- 算法探究:线性时间选择问题
- 经典算法总结之线性时间做选择
- 线性时间解决最大子数组问题