让我们看一个最佳选择的例子,
x
(水平数组 A、B、C、D):
A x
B b x b
C x c
D d x
我们基于范围的递归可能是:让f(low,excluded)
表示子集中没有excluded
元素的两个选择元素(从数组1到n
)之间的最大最近距离,其中low
是最低的选择元素。然后:
(1)
f(low, excluded) when |excluded| = n-1:
max(low)
for low in the only permitted array
(2)
f(low, excluded):
max(
min(
a - low,
f(a, excluded')
)
)
for a ≥ low, a not in excluded'
where excluded' = excluded ∪ {low's array}
我们可以限制a
。一方面,我们能够达到的最大值是
(3)
m = (highest - low) / (n - |excluded| - 1)
这意味着 a
不需要比 low + m
更高。
其次,我们可以为所有的 f(a, excluded')
存储结果,以 excluded'
为键(我们有2^10个可能的键),每个键对应一个按 a
排序的装饰二叉树。装饰将是右子树中可实现的最高结果,这意味着我们可以在对数时间内找到所有 f(v, excluded'), v ≥ a
的最大值。
后者建立了一种支配关系,显然我们对于更大的 a
和更大的 f(a, excluded')
都感兴趣,以便在(2)中最大化 min
函数。选择一个中间的 a
,我们可以使用二分查找。如果我们有:
a - low < max(v, excluded'), v ≥ a
where max(v, excluded') is the lookup
for a in the decorated tree
然后我们向右看,因为max(v, excluded)
表示右侧有更好的答案,其中a - low
也更大。
如果我们有:
a - low ≥ max(v, excluded), v ≥ a
然后我们记录这个候选项并向左查看,因为向右,答案固定为max(v, excluded)
,鉴于a-low
不能减少。
为了在范围[low, low + m]
(见(3))上进行二进制搜索,而不是在一开始合并和标记所有数组,我们可以将它们保持分开,并比较当前允许从中选择a
的每个数组中最接近mid
的候选项。(树具有混合结果,由子集键入。)(这部分的流程对我来说不是完全清楚的。)
使用此方法的最坏情况,鉴于n = C
是常数似乎是
O(C * array_length * 2^C * C * log(array_length) * log(C * array_length))
C * array_length is the iteration on low
Each low can be paired with 2^C inclusions
C * log(array_length) is the separated binary-search
And log(C * array_length) is the tree lookup
简化:
= O(array_length * log^2(array_length))
实际上,可能会有许多提前退出的死胡同分支,无法进行完整选择。
如果不清楚,迭代是在选择中固定的最低元素上进行的。换句话说,我们希望对于所有不同的low
和excluded
,得到最佳的f(low, excluded)
。对于自下而上,我们将从最高值向下迭代,因此我们迭代时存储a
的结果。