164. Maximum Gap

解法

求排序后相邻数的差距的最小值,如果使用基于比较的排序绝对是 O ( n l o g n ) O(nlogn) O(nlogn)的。
所以要考虑 O ( n ) O(n) O(n)的排序算法:计数排序、基数排序和桶排序
由于数字出现的范围是0~0x7fffffff,所以直接计数排序不行,从后两个上面考虑

解法一:基数排序

每次基数排序的时候可以使用计数排序【……嗯没错官解用的是计数排序

class Solution(object):
    def maximumGap(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        if n<2:
            return 0
        maxn = max(nums)

        exp = 1
        radix = 10

        while maxn/exp:
            sort_nums = [0] * n
            from collections import defaultdict
            counter = defaultdict(int)
            for num in nums:
                counter[(num/exp)%radix] += 1
            for i in xrange(1, radix):
                counter[i] += counter[i-1]
            for i in xrange(n-1, -1, -1):
                counter[(nums[i] / exp) % radix] -= 1
                sort_nums[counter[(nums[i]/exp)%radix]] = nums[i]
            nums = sort_nums
            exp *= 10

        ans = 0
        for i in xrange(1, n):
            ans = max(ans, nums[i]-nums[i-1])
        return ans

解法二:桶排序

根本想不到……
假设数组里有 n n n个数, a m a x a_{max} amax a m i n a_{min} amin分别是最大值和最小值,那么数组里一共有n-1个间隔,想像一个数轴,显然当除了 a m a x a_{max} amax a m i n a_{min} amin之外的n-2个数均匀分布的时候,最大的间隔最小: M a x G a p ≥ a m a x − a m i n n − 1 MaxGap\ge\frac{a_{max}-a_{min}}{n-1} MaxGapn1amaxamin,由于数都是整数,所以要取个上界:
M a x G a p ≥ ⌈ a m a x − a m i n n − 1 ⌉ MaxGap\ge\lceil\frac{a_{max}-a_{min}}{n-1}\rceil MaxGapn1amaxamin
也就是说,如果两个数的间隔小于 ⌈ a m a x − a m i n n − 1 ⌉ \lceil\frac{a_{max}-a_{min}}{n-1}\rceil n1amaxamin,我们没必要比较,因为答案肯定不会是它。这样我们可以把满足这个条件的数都放到一个桶里,这样我们需要考虑的间隔只有桶间的间距,即桶i的最大值和桶i+1的最小值的差。

由于桶大小为 B u c k e t S i z e BucketSize BucketSize的时候,它里面的数的间距一定小于 B u c k e t S i z e BucketSize BucketSize,所以桶的大小为:
B u c k e t S i z e = ⌈ a m a x − a m i n n − 1 ⌉ BucketSize=\lceil\frac{a_{max}-a_{min}}{n-1}\rceil BucketSize=n1amaxamin
举个例子:桶大小为4时,B[0]={0,1,2,3}B[1]=4,5,6,7

那么总共涉及多少个桶呢?我们的问题相当于是要把在 0 , . . . , a m a x − a m i n 0,...,a_{max}-a_{min} 0,...,amaxamin间的数放到桶里,所以桶的个数取决于最大值所在的桶的编号,由于桶是由0开始编号的,所以要+1,桶的个数为:
N u m B u c k e t s = ⌊ a m a x − a m i n B u c k e t S i z e ⌋ + 1 NumBuckets = \lfloor\frac{a_{max}-a_{min}}{BucketSize}\rfloor+1 NumBuckets=BucketSizeamaxamin+1

class Solution(object):
    def maximumGap(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        if n<2:
            return 0
        maxn = 0
        minn = 0x7fffffff
        for num in nums:
            maxn = max(maxn, num)
            minn = min(minn, num)

        bucket_size = int(math.ceil(1.0*(maxn-minn)/(n-1)))
        if bucket_size == 0:
            return 0
        nb = (maxn-minn)/bucket_size+1
        buckets = {}
        for num in nums:
            no = (num-minn)//bucket_size
            if no not in buckets:
                buckets[no] = [num,num]
            elif num>buckets[no][1]:
                buckets[no][1] = num
            elif num<buckets[no][0]:
                buckets[no][0] = num
        ans = 0
        nowmax = None
        for i in xrange(nb):
            if i in buckets:
                if nowmax is not None:
                    ans = max(ans, buckets[i][0]-nowmax)
                nowmax = buckets[i][1]
        return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值