如果允许预处理并且不计入时间复杂度,只需使用它来构建子列表,以便您可以有效地找到您正在寻找的元素。与大多数优化一样,这以空间换时间。
您的预处理步骤是获取原始n
数字列表并创建许多新的子列表。
这些子列表中的每一个都是原始的一部分,从n
第 th 个元素开始,扩展m
元素,然后排序。所以你的原始清单:
{3, 1, 7, 5, 9}
给你:
list[0][0] = {3}
list[0][1] = {1, 3}
list[0][2] = {1, 3, 7}
list[0][3] = {1, 3, 5, 7}
list[0][4] = {1, 3, 5, 7, 9}
list[1][0] = {1}
list[1][1] = {1, 7}
list[1][2] = {1, 5, 7}
list[1][3] = {1, 5, 7, 9}
list[2][0] = {7}
list[2][1] = {5, 7}
list[2][2] = {5, 7, 9}
list[3][0] = {5}
list[3][1] = {5,9}
list[4][0] = {9}
这不是一个便宜的操作(在时间或空间上),因此您可能希望在列表上维护一个“脏”标志,以便您仅在执行修改操作(插入、删除、更改)后第一次执行它。
事实上,您可以使用惰性求值来提高效率。基本上在您开始和执行修改操作时将所有子列表设置为空列表。然后,每当您尝试访问子列表并且它为空时,请在尝试从中获取第k
th 值之前计算该子列表(并且仅那个)。
这样可以确保仅在需要时评估子列表并缓存以防止不必要的重新计算。例如,如果您从不要求从 3 到 6 子列表中的值,则永远不会计算它。
创建所有子列表的伪代码基本上是(for
两端都包含循环):
for n = 0 to a.lastindex:
create array list[n]
for m = 0 to a.lastindex - n
create array list[n][m]
for i = 0 to m:
list[n][m][i] = a[n+i]
sort list[n][m]
惰性求值的代码稍微复杂一点(但只是一点点),所以我不会为此提供伪代码。
然后,为了找到范围内的k
第 th 最小数(其中和是原始索引),您只需查找,这是一个非常快速的 O(1) 操作:i
j
i
j
lists[i][j-i][k-1]
+--------------------------+
| |
| v
1st in range [3,4] (values 5,9), list[3][4-3=1][1-1-0] = 5
2nd in range [1,3] (values 1,7,5), list[1][3-1=2][2-1=1] = 5
3rd in range [0,2] (values 3,1,7), list[0][2-0=2][3-1=2] = 7
| | ^ ^ ^
| | | | |
| +-------------------------+----+ |
| |
+-------------------------------------------------+
这是一些 Python 代码,它显示了这一点:
orig = [3,1,7,5,9]
print orig
print "====="
list = []
for n in range (len(orig)):
list.append([])
for m in range (len(orig) - n):
list[-1].append([])
for i in range (m+1):
list[-1][-1].append(orig[n+i])
list[-1][-1] = sorted(list[-1][-1])
print "(%d,%d)=%s"%(n,m,list[-1][-1])
print "====="
# Gives xth smallest in index range y through z inclusive.
x = 1; y = 3; z = 4; print "(%d,%d,%d)=%d"%(x,y,z,list[y][z-y][x-1])
x = 2; y = 1; z = 3; print "(%d,%d,%d)=%d"%(x,y,z,list[y][z-y][x-1])
x = 3; y = 0; z = 2; print "(%d,%d,%d)=%d"%(x,y,z,list[y][z-y][x-1])
print "====="
正如预期的那样,输出是:
[3, 1, 7, 5, 9]
=====
(0,0)=[3]
(0,1)=[1, 3]
(0,2)=[1, 3, 7]
(0,3)=[1, 3, 5, 7]
(0,4)=[1, 3, 5, 7, 9]
(1,0)=[1]
(1,1)=[1, 7]
(1,2)=[1, 5, 7]
(1,3)=[1, 5, 7, 9]
(2,0)=[7]
(2,1)=[5, 7]
(2,2)=[5, 7, 9]
(3,0)=[5]
(3,1)=[5, 9]
(4,0)=[9]
=====
(1,3,4)=5
(2,1,3)=5
(3,0,2)=7
=====