给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度0(N),且要求不能用非基于比较的排序。
求解:
利用桶。 ①准备N个数,准备N+1个桶。
②遍历数组找最小值min和最大值max
1.如果min=max,数组是一种数,差值为0;
2.如果min!=max:
则①最小值放在0号桶,最大值放在第N号桶,中间数值等分为N+1份放入中间的桶中。
****中间必有一个空桶。
排序后的相邻数:1.在一个桶(内部差值一定是不需要的)
2.不在一个桶(最大差值来自不同的桶,前提是桶内不止一个数(除了例子a))
例子a:
左边是非空桶有max 中间是空桶 右边是非空桶min (空桶左右非空桶)
max与min的差值大于桶表示的范围
①找非空桶的前一个非空桶的最大值,记录相减差
②为什么不直接找空桶?
当空桶前后的非空桶只进入一个数值后:
A(10-19) B(20-29) C(39-39) D(40-49)
19 null 30 49
这种情况下,AC相差11,CD相差19.所以不直接找空桶。
代码如下:
1 public static int maxGap(int [] nums) { 2 3 if(nums==null||nums.length<2) { 4 return 0; 5 } 6 7 int len =nums.length;//数组长度 8 int min =Integer.MAX_VALUE;//系统最大值做数组中的最小值 9 int max=Integer.MIN_VALUE;//系统最小值做数组中的最大值 目的遍历找到最小值最大值 10 11 for(int i=0;i<len;i++) { 12 min=Math.min(min, nums[i]); 13 max=Math.max(max, nums[i]); 14 } 15 //更新最值 16 if(min==max) { 17 return 0; 18 } 19 //长度都位N+1 20 //每个桶的三组信息 21 boolean[] hasNum=new boolean[len+1]; 22 int [] maxs=new int[len+1]; 23 int [] mins=new int[len+1]; 24 int bid =0; 25 26 for(int i=0;i<len;i++) {//重新遍历整个数组 27 //确定当签署属于几号桶 28 bid=bucket(nums[i],len,min,max); 29 //数组放入桶中后,比较更新最值 30 mins[bid]=hasNum[bid]?Math.min(mins[bid], nums[i]):nums[i]; 31 maxs[bid]=hasNum[bid]?Math.max(maxs[bid], nums[i]):nums[i]; 32 //更新信息 33 hasNum[bid]=true; 34 } 35 36 int res=0; 37 int lastMax=maxs[0]; 38 int i=1; 39 //找到每一个非空桶和左边最近的非空桶 40 for(;i<len;i++) { 41 //用当前最小值——前一个桶的最大值 42 if(hasNum[i]){ 43 //差值; 44 res=Math.max(res, mins[i]-lastMax); 45 lastMax=maxs[i]; 46 } 47 } 48 //返回差值 49 return res; 50 } 51 52 public static int bucket(long num, long len, long min, long max) {//num 数值,len 桶的个数 53 // TODO 自动生成的方法存根 54 //确定来自哪个桶 55 return (int) ((num-min)*len/(max-min)); 56 } 57 58 /* 59 //对数器测试 60 public static int comparator(int[] nums) { 61 if(nums ==null||nums.length<2) { 62 return 0; 63 } 64 65 Arrays.sort(nums);//系统内置排序 66 int gap=Integer.MIN_VALUE; 67 for(int i=1;i<nums.length;i++) { 68 gap=Math.max(nums[i]-nums[i-1], gap); 69 } 70 return gap; 71 } 72 73 //随机生成数组 74 public static int[] generatateArray(int maxSize,int maxValue) { 75 int[] arr=new int[(int) ((maxSize+1)*Math.random())]; 76 for(int i=0;i<arr.length;i++) { 77 arr[i]=(int)((maxValue+1)*Math.random())-(int)(maxValue*Math.random()); 78 return arr; 79 } 80 81 //复制主数组 82 83 84 public static void main(String[] args) { 85 int testTime=50000; 86 int maxsize=100; 87 int maxvalue=100; 88 boolean succeed=true; 89 90 for(int i=0;i<testTime;i++) { 91 int [] arr1=generatateArray(maxSize,maxValue); 92 int [] arr2=copyArray(arr1); 93 94 if(maxGap(arr1)!=comparator(arr2)) { 95 succeed=false; 96 break; 97 } 98 } 99 System.out.println(succeed?"ok!":"No"); 100 } 101 } 102 103 private static int[] copyArray(int[] arr) { 104 // TODO 自动生成的方法存根 105 if (arr == null) { 106 return null; 107 } 108 int[] res = new int[arr.length]; 109 for (int i = 0; i < arr.length; i++) { 110 res[i] = arr[i]; 111 } 112 return res; 113 } 114 */ 115 public static void main(String[] args) { 116 int a[] = {23,45,2,78,6,88,9,10,24}; 117 maxGap(a); 118 System.out.println(maxGap(a)); 119 }