解法
求排序后相邻数的差距的最小值,如果使用基于比较的排序绝对是
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}
MaxGap≥n−1amax−amin,由于数都是整数,所以要取个上界:
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
MaxGap≥⌈n−1amax−amin⌉
也就是说,如果两个数的间隔小于
⌈
a
m
a
x
−
a
m
i
n
n
−
1
⌉
\lceil\frac{a_{max}-a_{min}}{n-1}\rceil
⌈n−1amax−amin⌉,我们没必要比较,因为答案肯定不会是它。这样我们可以把满足这个条件的数都放到一个桶里,这样我们需要考虑的间隔只有桶间的间距,即桶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=⌈n−1amax−amin⌉
举个例子:桶大小为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,...,amax−amin间的数放到桶里,所以桶的个数取决于最大值所在的桶的编号,由于桶是由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=⌊BucketSizeamax−amin⌋+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