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.
思路: 给定一个乱序的数组,求出按照排序的序列两个相邻数字之间的最大差值,但是要求时间复杂度和空间复杂度都是线性的,就不能用快速排序等先排序。可以采用桶排序,当要排序的数组内的元素是均匀分布的时候,桶排序的时间复杂度为o(n)。
先扫描一遍数组,求出数组的最大值max和最小值min。就是说数组中的元素的大小在min和max之间,一共n个数,当这n个数平均分布在[min,max]之间的话,那么最大的间隔为gap为(max-min)/(n-1),当然数组中的这n个数不一定是均匀分布,说明最大的间隔肯定是大于等于(max-min)/(n-1)的。
设gap=(max-min)/(n-1)
那么可也申请把这n个元素放在n-1个桶里,第1个桶存储的是在[min,min+gap]范围里面的元素,第2个桶存储的是在[min+gap,min+2*gap]范围里面的元素,依次类推第n-1个桶存放的是[min+(n-2)*gap,min+(n-1)*gap]范围里面的元素。这样的话,后一个桶中的元素肯定比前一个桶中的元素大。
又由于每个桶内的元素最多相差gap,所以说最大间隔肯定不在桶内,肯定是在桶与桶之间。 只要记录下每一个桶内的最大值和最小值,那么相邻桶之间的元素的间隔为后一个桶中最小的元素减去前一个桶中最大的元素。扫描一遍所有桶中最大的元素和最小的元素,那么最大的间隔也就求出来了。
现在还存在一个问题,对于nums[i],怎么找出nums[i]究竟应该存放在哪一个桶中的呢,用bid记录nums[i]应该存放的桶的下标,那么bid=(nums[i]-min)/gap,且gap=(max-min)/(n-1);
所以bid=(n-1)((nums[i]-min)/(max-min)),其中(nums[i]-min)/(max-min)始终在0到1之间,所以如果用整数的除法来算nums[i]不等于max的时候bid始终是为0的,所以要转化为浮点数的除法,则bid=(n-1)(1.0*(nums[i]-min)/(max-min))
public class Solution {
public int maximumGap(int[] nums) {
int n=nums.length;
if(n<2) return 0;
int res=-1;
int min=nums[0];
int max=nums[0];
for(int i=1;i<n;i++)
{
min=min>nums[i] ? nums[i] : min;
max=max>nums[i] ? max : nums[i];
}
if(max-min==0) return 0;
int[] min_bs=new int[n+1];
int[] max_bs=new int[n+1];
for(int i=0;i<n;i++)
{
int bid= (int)((n-1) * (1.0 * (nums[i] - min) / (max - min)));
if(min_bs[bid]==0 || min_bs[bid] > nums[i]) min_bs[bid]=nums[i];
if(max_bs[bid]==0 || max_bs[bid] <nums[i]) max_bs[bid]=nums[i] ;
}
min=max_bs[0];
for(int i=1;i<=n;i++)
{
if(min_bs[i]==0) continue;
res=res > (min_bs[i]-min) ? res : min_bs[i]-min;
min=max_bs[i];
}
return res;
}
}