有一个整形数组A,请设计一个复杂度为O(n)的算法,算出排序后相邻两数的最大差值。
给定一个int数组A和A的大小n,请返回最大的差值。保证数组元素多于1个。
public class 相邻两数最大差值 {
public int maxGap(int[] A, int n) {
int gapValue[] = new int[n - 1];
int k = 0;
Arrays.sort(A);
for (int i = 0; i < n - 1 && k < n - 1; i++) {
gapValue[k++] = A[i + 1] - A[i];
}
int max=Integer.MIN_VALUE;
for(int i=0;i<n-1;i++){
if (gapValue[i]>max) {
max=gapValue[i];
}
}
return max;
}
/*
* 另一种方法:
* 最优解时间复杂度O(N),额外空间复杂度O(N)
* 思想来自桶排序(和数组范围无关)
* 1、遍历数组,找到数组的最大值和最小值
* 2、在最大值和最小值范围内分成n个等量的空间,每个区间分别对应一个桶
* 3、遍历数组的每一个值,除了把最大值装在第n+1个桶外,把每一个值放在对应的区间里
* 4、因为有n个数,n+1个桶,所以中间一定有空桶,因为同一个桶内差值不大,所以只需要考虑桶前面的一个数,和桶后面的数之间的差值
*/
public static int MaxGap(int [] A,int n){
if (A==null || A.length<2) {
return 0;
}
int min=Integer.MAX_VALUE;
int max=Integer.MIN_VALUE;
for(int i=0;i<n;i++){
max=Math.max(max, A[i]);
min=Math.min(min, A[i]);
}
if (min==max) {
return 0;
}
int len=A.length;
int mins[]=new int[len+1];//存放每个桶中的最小值,存入元素时更新此
int maxs[]=new int [len+1];
boolean hasNum[] = new boolean[len+1];//用来标记是否为空桶
//向桶中放入元素
int bid=0;
for(int i=0;i<len;i++){
bid=bucket(A[i], len, min, max);//第几只桶
mins[bid]=hasNum[bid]?Math.min(mins[bid], A[i]):A[i];//如果hasNum为true,mins[bid]就等于该数与上一个该桶中的最小数比较较小的数
maxs[bid]=hasNum[bid]?Math.max(maxs[bid], A[i]):A[i];
hasNum[bid]=true;
}
//放好元素后,开始计算最大差值
int gap=0;
int preMax;//记录前一个桶中的最大值
int nextMin;//记录后一个桶中的最小值
int i=0;
while(i<len+1){
//寻找第一个空桶
while(i<len+1 && hasNum[i]){
i++;
}
if (i>=len+1) {
break;
}
preMax=maxs[--i];
i++;
//继续循环,找下一个非空的桶(将空桶遍历完)
while(i<len+1 && !hasNum[i]){
i++;
}
//跳出循环后就是非空的桶
nextMin=mins[i];
gap=gap>(nextMin-preMax)?gap:(nextMin-preMax);
}
return gap;
}
//计算元素改放在第几桶
public static int bucket(long num,long len, long min, long max){
return (int) ((num-min)*len/(max-min));//len为等量区间的数目,即桶的的数目(该过程一共需要len+1只桶)
}
public static void main(String[] args) {
int A[]={2,1,3,4,7,8,9};
int gap=MaxGap(A, A.length);
System.out.println(gap);
}
}