将矩阵视为一组行。在每一行中都有最小和最大有效值的索引。如果您知道这些索引,则可以在 O(1) 中计算该行中有效值的数量。 (有效是指 M[i,j] 和 M[i0,j0] 之间的值。)
现在,矩阵已排序。让我们取下限:(i,j)。
如果要查找上一行中最小有效值的索引,它必须位于 (i,j) 的右侧。这是因为正上方 (i,j) 必须有无效(太小)的值。
如果要在下一行中找到最小有效值的索引,它必须位于 (i,j) 的左侧(或正下方)。
因此,您最多需要在矩阵上走 2n 个“步”,才能找到每一行的下限索引。上限也是如此。所以你的步行是O(n),那么计算每行有效值的数量是O(n),因此总时间是O(n)。
使用此算法可以解决中位数问题。首先请注意,如果您计算前一个问题的解决方案,您可以使用每行中边界值的索引在线性时间内随机选择一个有效值。然后可以通过二等分算法计算中位数:
selection_find(M, i0,j0, i2,j2, K):
# Find K-th smallest number between M(i0,j0) and M(i2,j2)
# assumption: M(i0,j0)<M(i2,j2)
N := number of values between M(i0,j0) and M(i2,j2)
# assumption: k<N
Pick at random i1,j1 so that M(i0,j0)<M(i1,j1)<M(i2,j2)
L := number of values between M(i0,j0) and M(i1,j1)
if L==K:
The answer is M(i1,j1)
if L<K:
The answer is selection_find(M, i1,j1, i2,j2, K-L)
if L>K:
The answer is selection_find(M, i0,j0, i1,j1, K)
median_find(M):
The answer is selection_find(M, 1,1, n,n, n²/2)
每一步都需要 O(N)。将有 O(log N²)=O(2log N)=O(log N) 步骤(每个步骤应将考虑的值减半)。因此总复杂度为 O(NlogN)。