Python时间复杂性(运行时) def f2(L): 总和=0 i=1 而我

Python时间复杂性(运行时) def f2(L): 总和=0 i=1 而我,python,big-o,Python,Big O,设n是传递给此函数的列表的大小。以下哪项最准确地描述了此函数的运行时如何随着n的增长而增长 (a) 它像n一样线性增长。 (b) 它是二次增长的,就像n^2一样 (c) 它的增长小于线性增长。 (d) 它不仅仅是二次增长 我不明白你是如何理解函数的运行时间和n的增长之间的关系的。有人能给我解释一下吗?我不是计算机科学专业的学生,我也不认为自己对这类理论有很强的掌握,但我认为从我的角度来看,有人可能会尝试给出一个答案 您的函数总是需要时间来执行,如果它在不同长度的列表参数上运行,那么运行该函数所需

设n是传递给此函数的列表的大小。以下哪项最准确地描述了此函数的运行时如何随着n的增长而增长

(a) 它像n一样线性增长。 (b) 它是二次增长的,就像n^2一样

(c) 它的增长小于线性增长。 (d) 它不仅仅是二次增长


我不明白你是如何理解函数的运行时间和n的增长之间的关系的。有人能给我解释一下吗?

我不是计算机科学专业的学生,我也不认为自己对这类理论有很强的掌握,但我认为从我的角度来看,有人可能会尝试给出一个答案

您的函数总是需要时间来执行,如果它在不同长度的列表参数上运行,那么运行该函数所需的时间将与该列表中的元素数量有关

让我们假设处理长度==1的列表需要1个单位的时间。问题是,列表的大小变大与此函数执行时间的增加之间的关系

此链接分解了大O表示法的一些基础知识:

如果它是O(1)复杂度(这实际上不是你的A-D选项之一),那么它意味着无论L的大小,复杂度永远不会增长。显然,在你的例子中,它是在做一个while循环,依赖于相对于L的长度增长一个计数器
i
。我将关注
i
正在被乘以的事实,为了说明完成while循环所需的时间与L的长度之间的关系。基本上,试着比较while循环在len(L)的不同值下需要执行多少个循环,然后这将确定您的复杂性。通过while循环,1个时间单位可以是1次迭代

希望我在这里做出了一些贡献,因为我自己在这方面缺乏专业知识

更新

基于CH3KA的注释,如果您在<<代码> > 循环中做了更多的事情,那么您还必须考虑每个循环的复杂度。但因为你的,就像它后面的数学一样,我们可以忽略这些复杂性

这里有一个快速而肮脏的方法来发现:

def f2(L):
    sum = 0
    i = 1
    while i < len(L):
        sum = sum + L[i]
        i = i * 2
    return sum
导入matplotlib.pyplot作为plt
def f2(L):
总和=0
i=1
次数=0
而我
。。。导致


横轴是L的大小,纵轴是函数循环的多少倍;从这一点来看,big-O应该是非常明显的。

它是
O(log(len(L))
,因为列表查找是一个恒定的时间操作,与列表的大小无关。

当您查看函数时,您必须确定列表的大小将如何影响将发生的循环数

在您的特定情况下,让我们增加n,看看while循环将运行多少次

import matplotlib.pyplot as plt

def f2(L):
    sum = 0
    i = 1
    times = 0
    while i < len(L):
        sum = sum + L[i]
        i = i * 2
        times += 1    # track how many times the loop gets called
    return times

def main():
    i = range(1200)
    f_i = [f2([1]*n) for n in i]
    plt.plot(i, f_i)

if __name__=="__main__":
    main()
看到模式了吗?现在回答你的问题,是不是:

n = 0, loop = 0 times
n = 1, loop = 1 time
n = 2, loop = 1 time
n = 3, loop = 2 times
n = 4, loop = 2 times

Checkout对实证结果的回答是:)

考虑输入长度n=10时会发生什么。现在考虑如果输入大小加倍到20,会发生什么。运行时间也会加倍吗?那么它是线性的。如果运行时增长了因子4,那么它是二次的。等等。

好的,因为这是家庭作业:

代码如下:

(a) It grows linearly, like n does. (b) It grows quadratically, like n^2 does.

(c) It grows less than linearly. (d) It grows more than quadratically.
这些显然是常数时间,与L无关。 在循环中,我们有:

sum = 0
i = 1
# [...]
return sum
循环执行了多少次? 这显然取决于L的大小。 让我们调用
循环(L)

所以我们得到了

loops(L)*(timelookup(L)+const)

作为一个好人,我要告诉你,列表查找在python中是不变的,所以它可以归结为

O(循环(L))
(常量因子被忽略,正如big-O惯例所暗示的那样)

根据
L
len()
,您多久循环一次

(a) 列表(b)中的项目与列表中的项目一样频繁


(c) 由于列表(d)中的项目比(b)中的项目少,这似乎是正确的,因为正如ch3ka指出的,列表查找是
O(1)
。更一般地说,我们需要测量的不是迭代次数,而是时间。但是,它也可以直接测量并用
matplotlib
绘制。因为列表查找是O(1),所以我们可以假设迭代次数将~=所用时间。这个问题也是关于列表的。@G19Fantaic是的,但是OP可能不知道这个事实,所以我认为值得指出这个微妙的区别。这是逻辑中的一个隐含步骤,我想变得更明确,仅此而已。你应该真正指出,这只是因为
L[I]
O(1)
额外资源:,更多资源:
sum = 0
i = 1
# [...]
return sum
    sum = sum + L[i] # time to lookup L[i] (`timelookup(L)`) plus time to add to the sum (obviously constant time)
    i = i * 2 # obviously constant time