正确的问题应该是:
在数组 A=[a0,a2,..an] 中找到两个元素 a, b 使得它们之间的差小于或等于: (M-m)/n > | a - b|其中 M=max(A) 且 m = min(A)。
我建议的解决方案是使用 quickSelect,预期时间复杂度为 O(n)。实际最坏的情况是 O(n^2)。这是一个折衷,因为大多数时候它是 O(n),但它需要 O(1) 的空间复杂度(如果 quickSelect 是迭代实现的,并且我的伪代码是用 while 循环而不是递归实现的)。
主要思想:
在每次迭代中,我们使用 quickSelect 找到中值,如果 |max - medianValue | > |min - medianValue | 我们知道我们应该搜索数组的左侧。那是因为我们两边的元素数量相同,但中值更接近最小值,因此应该存在它们之间差异较小的元素。否则我们应该在右侧搜索。
每次我们都知道子数组的新最大值或最小值应该是中位数。
我们继续搜索,每次将数组的大小除以 2。
预期中的运行时证明:
假设对 n 个元素的每次迭代都以 c*n + d 为期望值。
因此我们有:
(cn + d) + 0.5(cn + d) + 0.25 (c*n + d) + … +(1/log_{2} (n)) (cn + d)
n +….) = (1+0.5+0.25+….)d + cn(1+0.5+0.25+….) =
=2*d +2*c*n
意味着我们有 O(n) 的期望。
使用递归的伪代码:
run(arr):
M = max(arr)
m = min(arr)
return findPairBelowAverageDiff(arr,0,arr.length,m,M)
findPairBelowAverageDiff(arr, start, end, min, max) :
if start + 1 < end:
medianPos = start + (end - start) / 2
// median that is between start and end in the arr.
quickSelect(arr, start, medianPos, end)
if max - arr[medianPos] > arr[medianPos] - min:
return findPairBelowAverageDiff(arr, start, medianPos,
min, arr[medianPos])
else :
return findPairBelowAverageDiff(arr, medianPos,
end, arr[medianPos], max);
else :
return (arr[start], arr[start + 1])