【问题标题】:Empirically measuring time complexity of QuickSelect经验性测量 QuickSelect 的时间复杂度
【发布时间】:2021-04-03 11:16:15
【问题描述】:

我知道时间复杂度应该是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, start, end)
    while pivot != k - 1:
        if pivot < k - 1:
            start, end = pivot, end
        else:
            start, end = start, pivot - 1
        pivot = insertPivot(array, start, 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))

【问题讨论】:

    标签: python algorithm time-complexity complexity-theory


    【解决方案1】:

    insertPivot 确实具有 O(N) 复杂性,因为您增加 i 并减少 j 直到 j 不再大于 i。然而,insertPivot 被嵌入到quickselect 内部的一个while 循环中。因此,无论quickselect 的复杂度如何,都会乘以insertPivot 的复杂度,因为在循环的每一步都会执行O(n) 复杂度的算法。如果pivot &lt; k - 1,则增加区间的左边界。否则你会减少到pivot - 1。因此,在循环中,您通过其左边缘和枢轴之间的差异来减少每一步的间隔大小。根据您可以使用什么函数来估算步数,您可以确定将线性复杂度中的 N 与什么相乘,从而得出实际复杂度。

    【讨论】:

    • "否则你将 end 减 1" - 不,你误读了代码。它将end 设置为pivot - 1,而不是end - 1
    • @user2357112supportsMonica 感谢您指出这一点!你是完全正确的。我在 Python 方面缺乏经验,使我难以阅读代码,这导致了这种疏忽 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 2015-02-28
    • 2018-06-18
    • 2016-02-13
    • 2012-08-14
    • 2019-01-08
    • 1970-01-01
    相关资源
    最近更新 更多