题目:
给定一个long类型无序数组,排序后求出相邻两个数的最大差值,并返回。(要求 时间复杂度为O(n))
解析:题中给出的是long类型的数组,因此数字有可能非常大,排除基数排序方法,容易看出这道题目不能用一般的排序方法。实现方法如下:
首先求出数组中元素的个数n、最小值min、最大值max;根据数据的个数建立桶:
设置桶的个数为n+1,将min~max范围的数平分为n+1等分依次作为这n+1个桶可放入
数的值范围。
例如:数组Arr[9]={0,45,47,27,22,31,83,23,99},其中n=9,min=0,max=99;因此
设置10个桶如下图:
具体操作如下:
遍历该数组,依次将数组中元素按照范围划分放入对应的桶中,显然桶1和桶10中必然分别存放有min和max,
由于有9个数,而桶个数为10个,所以在桶2~桶9之间至少存在一个空桶。可以知道桶内的最大差值最大情况为9,
空桶两边相邻非空桶之间最大差值最小情况为11。因此我们可以得到一个结论:相邻两个数的最大差值一定存在
于桶与桶之间,而不可能在同一个桶内。所以就不用关心一个桶内部的信息,只关心一个桶内的最大数和最小数
即可。且相邻非空桶之间后者的最小值与前者的最大值肯定是排完序后相邻的两个数。
给定三个数组:Boolean isEmpty[10],int Min[10],int Max[10],这三个数组每个位置信息作为每个桶
的状态(是否为空,最小值,最大值)
相邻非空桶之间后面一个桶的最小值减去前面一个桶的最大值为候选答案之一。遍历一遍该10个桶则可得到所求
答案。时间复杂度为:O(n),此题分析完毕。
代码如下:(非自己编写,懒的写)
package basic_class_01;
import java.util.Arrays;
public class Code_11_MaxGap {
public static int maxGap(int[] nums) {
if (nums == null || nums.length < 2) {
return 0;
}
int len = nums.length;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < len; i++) {
min = Math.min(min, nums[i]);
max = Math.max(max, nums[i]);
}
if (min == max) {
return 0;
}
boolean[] hasNum = new boolean[len + 1];
int[] maxs = new int[len + 1];
int[] mins = new int[len + 1];
int bid = 0;
for (int i = 0; i < len; i++) {
bid = bucket(nums[i], len, min, max);
mins[bid] = hasNum[bid] ? Math.min(mins[bid], nums[i]) : nums[i];
maxs[bid] = hasNum[bid] ? Math.max(maxs[bid], nums[i]) : nums[i];
hasNum[bid] = true;
}
int res = 0;
int lastMax = maxs[0];
int i = 1;
for (; i <= len; i++) {
if (hasNum[i]) {
res = Math.max(res, mins[i] - lastMax);
lastMax = maxs[i];
}
}
return res;
}
public static int bucket(long num, long len, long min, long max) {
return (int) ((num - min) * len / (max - min));
}
// for test
public static int comparator(int[] nums) {
if (nums == null || nums.length < 2) {
return 0;
}
Arrays.sort(nums);
int gap = Integer.MIN_VALUE;
for (int i = 1; i < nums.length; i++) {
gap = Math.max(nums[i] - nums[i - 1], gap);
}
return gap;
}
// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static void main(String[] args) {
int testTime = 500000;
int maxSize = 100;
int maxValue = 100;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
if (maxGap(arr1) != comparator(arr2)) {
succeed = false;
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
}
}