题目:给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度O(N),且要求不能用非基于比较的排序。
已知的基于比较的排序,最快也要O(N*logN),所以即时不用非基于比较的排序,也一定要用到桶的概念。
首先准备桶,如果数组有N个数,就准备N+1个桶,先遍历数组,找最小值和最大值,如果min!=max,就把min放入0号桶,max放入N号桶,把min到max的范围,等分成N+1份,分别对应N+1个桶,剩下的数,属于哪个范围就放入哪个桶,这样,N+1个桶中必定存在至少一个空桶,这就使得我们所要求的最大差值,大与单个桶的差值范围,最大差值就一定不会来自同一个桶中的两个数,最大差值一定来自前一个桶的最大值和后一个桶的最小值。
那么我们每个桶,也之需要记录是否进来过数,以及进过它的最小值和最大值。
然后从1号桶开始搜索,如果它空的,就直接跳下一个,如果它是非空的桶,就找到它左边最近非空的桶,记录它左边最近非空桶的max和它自己min的差值,我们要求的最大差值,一定就是这些差值中的最大值
#include<iostream>
#include <vector>
#include <cstring>
using namespace std;
//判断一个数该进哪个桶
int bucket(long num,long len,long min,long max){
return (int)((num-min)*len/(max-min));
}
int maxGap(vector<int>&nums){
if(nums.empty()||nums.size()<2)
return 0;
int len=nums.size();
int _min=10000;
int _max=-10000;
for(int i=0;i<len;i++){
_min=min(_min,nums[i]);
_max=max(_max,nums[i]);
}
if(_max==_min)
return 0;
bool hasNum[len+1];
memset(hasNum, false,sizeof(hasNum));
int maxes[len+1];
int mins[len+1];
int bid=0;
for(int i=0;i<len;i++){
bid=bucket(nums[i],len,_min,_max);
mins[bid]=hasNum[bid]?min(mins[bid],nums[i]):nums[i];
maxes[bid]=hasNum[bid]?max(maxes[bid],nums[i]):nums[i];
hasNum[bid]=true;
}
int res=0;
int lastMax=maxes[0];
int i=1;
for(;i<=len;i++){
if(hasNum[i]){
res=max(res,mins[i]-lastMax);
lastMax=maxes[i];
}
}
return res;
}
int main(){
vector<int>nums={178,34,35,245,13,5,25,3};
int ans=maxGap(nums);
cout<<ans;
}