LeetCode------Maximum Gap

本文介绍了一种基于桶排序的算法实现,用于求解数组中最大间距的问题。该算法首先找出数组的最大值和最小值,然后根据这些值确定桶的数量和容量,将数组中的元素分配到相应的桶中,并计算每个桶中的局部最大值和最小值,最后通过比较桶间的最大间距找到整个数组的最大间距。
摘要由CSDN通过智能技术生成

这里写图片描述

桶排序实现

(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));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值