问题描述:
Given an unsorted array, find the maximum difference between the successive elements in its sorted form.
Try to solve it in linear time/space.
Return 0 if the array contains less than 2 elements.
You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range.
Credits:
Special thanks to @porker2008 for adding this problem and creating all test cases.
分析:这道题我没做出来,自己总结原因是,对O(n)的排序算法不了解,以前只知道快排和归并排序是O(nlogn),但并不知道桶排序的时间复杂度是O(n)。
第二对桶排序的工作原理不了解,以为是value%n然后把元素分到不同的桶里,这样是错误的。这样根本起不到排序的作用。真正的方法是,找到一个数组里面的两个极限值(最大和最小值),然后求出平均每个桶能够包容的范围gapBucket。这样,当来一个新的元素后,它的相对差(nums[i]-min)然后对gap作商即为要投放的桶。
这里会发生碰撞,(在真正排序时,还需要再桶内进行二次排序,然后再整合,但是我们这里没关系,因为一个桶内的元素的差<\gapBucket)。而我们所求的max gap一定要大于这里的gap,为啥?
反证法:如果最大的gap小于gapBucket,那么gap*(N-1)<\gapBucket*(N-1) = max-min;
与事实不符,实际上,相邻两个元素之间的值可能大于gap,也可能小于gap,但是对于大于gap的情况,一定是两个相邻的有效桶(真正有元素)之间,且后者的最小值与前者的最大值之差。一定是这种情况。
代码如下:8ms
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
class Solution {
public:
int maximumGap(vector<int>& nums) {
int n = nums.size();
if(n<2)
return 0;
vector<int> maxBucket(n,INT_MIN);
vector<int> minBucket(n,INT_MAX);
int min = nums[0],max = nums[0];
for(int i = 1;i<n;i++){
if(nums[i]<min)
min = nums[i];
else if(nums[i]>max)
max = nums[i];
}
double gap = (double)(max-min)/(n-1);
for(int i = 0;i<n;i++){
int index = (int)((nums[i]-min)/gap);
maxBucket[index] = max(maxBucket[index],nums[i]);
minBucket[index] = min(minBucket[index],nums[i]);
}
//查找有效的gap between buckets
int res = 0;
int prevMax = -1;
int prevMin = -1;
for(int i = 0;i<n;i++){
if(maxBucket[i]<0)
continue;
if(prevMax>0){
int gap = minBucket[i]-prevMax;
if(gap>res)
res = gap;
}
prevMax = maxBucket[i];
prevMin = minBucket[i];
}
return res;
}
};