Leetcode 164. Maximum Gap

这道题先排序再遍历一遍能够直接AC,但是在讨论区有人提出了使用桶排序的方式,理论上比直接调库排序更加快,但实际上直接调库速度更快。

首先,定义max, min, N分别为数组最大值、最小值、以及数组长度,根据抽屉原理,显然maximum gap ≥ gap = round_up[(max - min) / (N-1)]。反证法如果maximum gap < gap,则会出现 min + (N-1)*maximum gap < max 的矛盾情况。

因此,设置k个桶,分别存放[min, min+gap), [min+gap, min+2*gap), [min+2*gap, min+3*gap)...范围的数字,这样maximum gap的两个数只会出现在不同的桶中,因此只需要对每个桶记录最大值和最小值即可。

import math
class Solution(object):
    def maximumGap(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) <= 1:
            return 0
        
        min_num = min(nums)
        max_num = max(nums)
        if max_num - min_num <= 1:
            return max_num - min_num

        # maximum gap >= gap
        gap = int(math.ceil((max_num - min_num) / (len(nums) - 1.0)))
        
        # 桶存放的nums范围=gap
        # 通过检查不同桶之间的最大值和最小值的gap可以得到nums数组的maximun gap
        # bucket[i]表示第i个桶存放的最小值
        bucket = [min_num]
        while bucket[-1] + gap - 1 < max_num:
            bucket.append(bucket[-1] + gap)
            
        # bucket_info 存放桶中最大值和最小值信息
        bucket_info = []
        for i in range(len(bucket)):
            bucket_info.append([])
        for num in nums:
            bucket_id = int((num - min_num) // gap)
            if not bucket_info[bucket_id]:
                bucket_info[bucket_id] = [num, num]
            else:
                bucket_info[bucket_id][0] = min(bucket_info[bucket_id][0], num)
                bucket_info[bucket_id][1] = max(bucket_info[bucket_id][1], num)
        result = gap

        # 第1个bucket和最后1个bucket一定不为空
        last_bucket_max = bucket_info[0][1]
        for i in range(1, len(bucket_info)):
            if not bucket_info[i]:
                continue
            buckets_gap = bucket_info[i][0] - last_bucket_max
            result = max(result, buckets_gap)
            last_bucket_max = bucket_info[i][1]
        return result

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值