[Leetcode] maximum gap
[1] https://leetcode.com/problems/maximum-gap/
这里具有使用桶的思想来对整数进行规整,通过详细的设计桶的大小,可以保证最大间隔一定大于等于桶的大小,从而保证最大间隔不会出现在桶的内部,而是桶之间。
这里的关键是如何设计桶的大小?
假设N个数字,均等分布,那么间隔是(max - min)/(N-1)
如果不是均等分布,一定存在大于(max - min)/(N-1)的间隔。
所以最大的间隔一定大于等于(max - min)/(N-1)
上面的证明,实际上有一个非常强的前提:(max - min)%(N-1)==0,但是实际当中并不一定是整除的情形,这时我们要对这个间隔上取整,即
ceil((max - min)/(N-1))
我是亮丽的分割线
证明:
假设所有的gap都是小于等于floor((max - min)/(N-1))的,那么
$min + \sum_{i=1}^{N-1}gap \le max$
所以至少存在一个gap大于$floor((max - min)/(N-1))$的,或者是大于等于$ceil((max - min)/(N-1))$的
这说明最大的gap不会比$ceil((max - min)/(N-1))$小。
在桶的内部,gap都是小于这个值得,所以最大的gap只能存在于桶之间。
这里的$ceil((max - min)/(N-1))$是一个非常极端的情况,桶只要尽可能的小都是对的,比如$ceil((max - min)/N)$
1 public class Solution { 2 public int maximumGap(int[] nums) { 3 if(nums==null||nums.length==0||nums.length==1) return 0; 4 int max = Integer.MIN_VALUE; 5 int min = Integer.MAX_VALUE; 6 for(int i: nums){ 7 max = Math.max(max,i); 8 min = Math.min(min,i); 9 } 10 //backet size应该尽量小 11 // 12 int backetsize = (int)Math.ceil((double)(max - min)/(nums.length)); 13 int [] maxmin = new int[3* nums.length]; 14 for(int i=0;i<maxmin.length;i++) maxmin[i]=-1; 15 for(int i=0;i<nums.length;i++){ 16 int num = nums[i]; 17 int backetindex = (num - min)/backetsize; 18 if(maxmin[backetindex*2]==-1){ 19 maxmin[backetindex*2]=maxmin[backetindex*2+1]=num; 20 }else{ 21 maxmin[backetindex*2+1] = Math.max(maxmin[backetindex*2+1],num); 22 maxmin[backetindex*2] = Math.min(maxmin[backetindex*2],num); 23 } 24 } 25 //search for the maximum gap 26 int pre = -1; 27 int maxgap = -1; 28 for(int i=0;i<nums.length;i++){ 29 if(maxmin[2*i+1]!=-1&&pre==-1){ 30 pre =maxmin[2*i+1]; 31 continue; 32 } 33 if(maxmin[2*i]!=-1){ 34 maxgap = Math.max(maxgap,maxmin[2*i]-pre); 35 pre = maxmin[2*i+1]; 36 } 37 } 38 return maxgap; 39 } 40 }