问题描述
我知道时间复杂度应该是 O(N)
。但是,当我凭经验对其进行测试时,会得到奇怪的结果。有人可以解释一下这是怎么回事吗?
def insertPivot(array,start,end):
pivot = end
i = start
j = end - 1
while i < j:
while array[i] < array[pivot] and i < j:
i += 1
while array[j] > array[pivot] and j > i:
j -= 1
array[i],array[j] = array[j],array[i]
if array[i] > array[pivot]:
array[i],array[pivot] = array[pivot],array[i]
pivot = i
return pivot
def quickselect(array,k):
start = 0
end = len(array) - 1
pivot = insertPivot(array,end)
while pivot != k - 1:
if pivot < k - 1:
start,end = pivot,end
else:
start,end = start,pivot - 1
pivot = insertPivot(array,end)
return array[k - 1]
这是我如何获得测量值
import random
import timeit
import numpy as np
av_times = dict()
for n in [10,100,500,1000,5000,10000]:
times = list()
array = list(range(n))
for _ in range(10):
random.shuffle(array)
k = random.randint(0,n)
times.append(
timeit.timeit(lambda: quickselect(array,k),number=10)
)
av_times[n] = sum(times) / len(times)
xx,yy = zip(*av_times.items())
xx,yy = np.log(xx),np.log(yy)
m,b = np.polyfit(xx,yy,1)
斜率系数m
为1.5
,这表明时间复杂度为O(N*sqrt(N))
解决方法
insertPivot
确实具有 O(N) 复杂度,因为您增加 i
并减少 j
直到 j
不再大于i
。但是,insertPivot
被嵌入到 quickselect
内的 while 循环中。因此,无论 quickselect
的复杂度如何,都会乘以 insertPivot
的复杂度,因为在循环的每一步都会执行 O(n) 复杂度的算法。如果 pivot < k - 1
,则增加间隔的左边界。否则,您将减少到 pivot - 1
。因此,在循环中,您将每一步的间隔大小减少其左边缘和枢轴之间的差异。根据您可以使用什么函数来近似计算步骤数,您可以确定将线性复杂度中的 N 与什么相乘,从而得出实际复杂度。