给定一个数组,求如果在排序之后,相邻两数的最大差值,要求时间复杂度O(n),且不能使用非基于比较的排序(也就是不能使用基数排序)
解题思路:
本题最简单最暴力的解法就是使用Arrays.sort(),然后遍历一遍就可以找到相邻两数的最大差值,但是要求时间复杂度为O(n),此方法就行不通了;还有一种方法就是采用桶排序。
- 遍历一遍数组,找到最大值和最小值。
- 将数组中数的范围按照数组长度 + 1进行等分,即(max - min) / (array.length + 1),划分到length + 1个桶中。
- 将数组中的数放入桶中。
- 遍历桶找出两个数的最大差值。
这两个数可能出现的地方为:空桶两侧的最大值和最小值或者相邻两个桶的最大值和最小值。
划分length + 1个桶的原因为保证至少有一个空桶,并且保证出现最大差值的两个数不可能命中到同一个桶中
public class MaxGap {
public static int maxGap(int[] arr){
if(arr == null || arr.length < 2)
return 0;
int min = arr[0]; //最大值
int max = arr[0]; //最小值
for (int i : arr) {
min = Math.min(min,i);
max = Math.max(max,i);
}
if(max == min){
return 0;
}
int size = arr.length + 1;
boolean[] hasNum = new boolean[size]; //该桶中是否有元素
int[] maxs = new int[size]; //该桶中的最大值
int[] mins = new int[size]; //该桶中的最小值
for(int i = 0;i < arr.length;i++){
int index = (arr[i] - min) * arr.length / (max - min); //根据数组元素求出在桶中的下标
mins[index] = hasNum[index] ? Math.min(mins[index],arr[i]) : arr[i]; //更新桶中的元素
maxs[index] = hasNum[index] ? Math.max(maxs[index],arr[i]) : arr[i];
hasNum[index] = true;
}
int result = 0;
int lastMax = maxs[0];
for(int i = 1;i < size;i++){
if(hasNum[i]){
result = Math.max(result,mins[i] - lastMax);
lastMax = maxs[i];
}
}
return result;
}
}