给出n个元素的排序序列。从长度为k的子序列的所有对中找到所有最小值中的最大值。
Here 1<=n<=10^5
and 2<=k<=n
For eg: [2, 3, 5, 9] and k = 3
there are 4 subsequences:
[2, 3, 5] - min diff of all pairs = 1
[2, 3, 9] - min diff of all pairs = 1
[3, 5, 9] - min diff of all pairs = 2
[2, 5, 9] - min diff of all pairs = 3
所以答案是所有最小差值= 3的最大值
幼稚的方法是找到所有k个长度的子序列,然后在每个子序列中找到最小值,然后在所有它们中找到最大值,但是由于约束条件而超时。
除此之外,我认为是找到最佳距离的序列,以使最小值变为最大值。
有人可以提供最佳且更好的解决方案吗?
答案 0 :(得分:0)
假设您的整数序列为a[i]
。然后,我的解决方案将及时O(n log((a[n-1]-a[0])/n))
找到答案。如果您的序列是浮点数,则它可能会在相似的时间内运行,但理论上可能会与O(n^3)
一样糟糕。
关键观察是这个。很容易从最小间隔至少为m
的第一个元素开始构造最紧凑的序列。只要取第一个元素,并且当其至少比您取的最后一个大m
大时,彼此取个。因此,我们可以编写一个构造此序列并跟踪3个数字的函数:
m
会导致更紧凑的序列。也就是说,与我们未包含的元素之间的最大差距。对于您的序列,如果我们以2的间隔进行此操作,我们会发现我们采用了3个元素,最小的间隔为3,如果我们寻找的间隔为2,我们将得到一个不同的序列1。
这是足够的信息,可以为所需的间隙长度构建二进制搜索。关键逻辑如下所示:
lower_bound = 0
upper_bound = (a[n-1] - a[0])/(k-1)
while lower_bound < upper_bound:
# Whether int or float, we want float to land "between" guesses
guess = (lower_bound + upper_bound + 0.0) / 2
(size, gap_found, gap_different) = min_gap_stats(a, guess)
if k < size:
# We must pick a more compact sequence
upper_bound = gap_different
else:
# We can get this big a gap, but maybe we can get bigger?
lower_bound = gap_found
如果我们为您的序列运行此函数,则首先将lower_bound
设置为0,将upper_bound
设置为7/2 = 3
(由于整数除法)。我们会立即找到答案。
如果具有相同值的浮点序列,则将花费更长的时间。我们首先尝试3.5,然后在3处得到具有不同决策的2序列。然后,我们尝试1.5,并在3处找到具有所需间隔的序列。
二分法搜索通常会使此过程的通过次数为对数。
但是,每次我们为实际的成对间隙的大小设置上限或下限。由于仅存在O(n^2)
个空缺,因此我们保证只需要很多次即可。