桶排序实现
(1)首先找出数组的最大值和最小值;
(2)然后要确定每个桶的容量,即为(最大值 - 最小值) / 元素个数 + 1
;
(3)在确定桶的个数,即为(最大值 - 最小值) / 桶的容量 + 1
,
(4)对于数组中的任意整数k,通过算式index = (k - 最小值) / 桶的容量
找出其桶的位置;
(5)然后需要在每个桶中找出局部最大值和最小值,最大间距的两个数不会在同一个桶中,而是一个桶的最小值和另一个桶的最大值之间的间距。原因是:考虑最极端的情况,数组的所有的元素都是均匀分布的,即每两个相邻元素之间的差值都是桶的容量,即:(最大值 - 最小值) / 元素个数 + 1
,所以只要不是均匀分布那必定有相邻元素之间差值小于桶的容量,则对应也必定有相邻元素之间差值大于桶的容量,所以最大间距的两个数肯定不会在同一个桶中,而是一个桶的最小值和另一个桶的最大值之间的间距
。
具体例子
现在有数组[1, 3, 5, 9]
。那么我们可以把它分成3个bucket来装,min表示在这个bucket范围中,存在的最小数和最大数。这个bucket的长度是最小可能的最大差值<只有在均匀分布时才可能>
。(如果哪个差值比这个还小,那么为了填补这个小差值,就必然存在另一个差值比它大,那么这个数组的最大差值就比当前bucket大。所以均分下来的bucket是最小可能的最大差值
)
b0: (1, 3) min = Integer.max, max = Integer.min
b1: (4, 6) min = Integer.max, max = Integer.min
b2: (7, 9) min = Integer.max, max = Integer.min
然后来看这个数组元素都位于哪个bucket里,用(nums(i) - min) / gap
得到,
//第一个数1在b0中,所以我们更新:
b0: (1, 3) min = 1, max = 1;
//第二个数3在b0中,所以我们更新:
//b0: (1, 3) min = 1, max = 3;
//第三个数5在b1中,所以我们更新:
b1: (4, 6) min = 5, max = 5;
.
.
依次这样下去。
因为每个bucket中的最大值-最小值就是我们最小的gap, 所以我们不用计算相邻的两个数,我们只要比较后一个bucket中的最小值和前一个bucket中的最大值相差多少,取最大相差的值就是最终的结果。注意考虑min和max两个边界值也要加进去。实例代码如下:
public int maximumGap2(int[] nums) {
if (nums == null || nums.length < 2) return 0;
int len = nums.length;
int max = nums[0], min = nums[0];
for (int i = 0; i < nums.length; i++) {
max = Math.max(max, nums[i]);
min = Math.min(min, nums[i]);
}
//Math.ceil返回大于等于参数x的最小整数,即对浮点数向上取整.,使bucket可以包含所有数
int gap = (int)Math.ceil((double)(max - min) / (len - 1));
int[] BucketsMIN = new int[len - 1];
int[] BucketsMAX = new int[len - 1];
Arrays.fill(BucketsMIN, Integer.MAX_VALUE);
Arrays.fill(BucketsMAX, Integer.MIN_VALUE);
for (int num : nums) {
//不考虑边界,所以把边界的min和max都拿出来,单独再考虑
if (num == min || num == max) continue;
int bucket = (num - min) / gap;
BucketsMIN[bucket] = Math.min(BucketsMIN[bucket], num);
BucketsMAX[bucket] = Math.max(BucketsMAX[bucket], num);
}
int result = 0;
int previous = min;
for (int i = 0; i < len - 1; i++) {
if (BucketsMIN[i] == Integer.MAX_VALUE && BucketsMAX[i] == Integer.MIN_VALUE) {
continue;
}
result = Math.max(result, BucketsMIN[i] - previous);
previous = BucketsMAX[i];
}
result = Math.max(result, max - previous);
return result;
}
@Test
public void test1() {
int arr[] = {1,3,5,9};
System.out.println(maximumGap2(arr));
}