这道题可以使用桶排序的方法和基数排序的方法,对这两个方法不了解的可以参考算法导论。
这两个排序算法都可以在线性时间内对在一定范围内的数据进行排序,是能够解这道题的理论基础。
是有桶排序的思路是:
首先,对数据进行根据桶进行划分。
然后,统计桶间的最大间隔。
gmax=max(num);gmin=min(num);
当对[gmin,gmax]的范围内的数据进行均匀划分桶时,桶的区间长度bucketSize为数据范围除以区间个数,即bucketSize=(gmax-gmin)/(n-1)+1;
因此,桶的个数bucketCnt=(gmax-gmin)/bucketSize+1;
此时,桶内数据的差值在bucketSize之内,而整体数据之间一定存在差值大于区间长度bucketSize的两个数,否则,所有数据之间的差值都在bucketSize之内,
那么所有数据的形成的范围不可能是[gmin,gmax]。
程序如下所示:
struct Bucket{
int bmin;
int bmax;
int bcnt;
Bucket(int x, int y, int z){
bmin=x;bmax=y;bcnt=z;
}
};
int maximumGap(vector<int> &num){
int n=num.size();
if(n<2) return 0;
if(2==n) return abs(num[1]-num[0]);
auto minMax=minmax_element(num.begin(),num.end());
int gMin=*minMax.first, gMax=*minMax.second;
int bucketSize=(gMax-gMin)/(n-1)+1;
int bucketCnt=(gMax-gMin)/bucketSize+1;
vector<Bucket>bucket(bucketCnt,Bucket(INT_MAX,INT_MIN,0));
for(int i=0;i<n;i++){
int k=(num[i]-gMin)/bucketSize;
bucket[k].bcnt++;
if(num[i]<bucket[k].bmin)bucket[k].bmin=num[i];
if(num[i]>bucket[k].bmax)bucket[k].bmax=num[i];
}
int pre=0,maxGap=0;
for(int i=1;i<bucketCnt;i++){
if(!bucket[i].bcnt)continue;
maxGap=max(maxGap,bucket[i].bmin-bucket[pre].bmax);
pre=i;
}
return maxGap;
}
使用基数排序时,参考别人的代码和C++11新特性,写出了下面AC的基于基数排序的解决方法
int maximumGap(vector<int> &num){
for(auto bit=0;bit<31;bit++)
stable_partition(num.begin(),num.end(),[bit](int x){return !(x&1<<bit);});
int maxGap(0);
for(unsigned i=1;i<num.size();i++) maxGap=max(maxGap,num[i]-num[i-1]);
return maxGap;
}
简单的利用了C++11的特性,加快了写代码地速度,并且更加简洁!
lambda函数[bit](int x){return !(x&1<<bit);}
和自动类型识别auto,才发现C++11有挺多好用的特性,了解的有点晚了,下次出新技术,要及时快速地了解。