微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

经验测量 QuickSelect 的时间复杂度

如何解决经验测量 QuickSelect 的时间复杂度

我知道时间复杂度应该是 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)

斜率系数m1.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 与什么相乘,从而得出实际复杂度。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。