2012-04-23 79 views
4
def f2(L): 
    sum = 0 
    i = 1 
    while i < len(L): 
     sum = sum + L[i] 
     i = i * 2 
    return sum 

設n是傳遞給該函數的列表L的大小。以下哪項最準確地描述了該函數的運行時間如何隨着n的增長而增長?Python的複雜性(運行時間)

(一)它呈線性增長,如N一樣。 (b)它像n^2那樣以二次方式增長。

(c)增長小於線性。 (d)它的增長高於二次方。

我不明白你怎麼找出功能的運行時間和n的增長之間的關係。有人可以向我解釋這個嗎?

+0

這功課嗎?請標記爲這樣。 – 2012-04-23 19:43:52

+2

不知道這是一個關於Python的問題,而不是關於big-O符號的問題。此外,它聞起來很像作業。 – 2012-04-23 19:43:59

+0

@CharlesDuffy不是* cyclomatic *複雜度是對源代碼複雜程度的測量嗎? – delnan 2012-04-23 19:45:02

回答

7

確定,因爲這是家庭作業:

這是代碼:

def f2(L): 
    sum = 0 
    i = 1 
    while i < len(L): 
     sum = sum + L[i] 
     i = i * 2 
    return sum 

這顯然是依賴於LEN(L)。

所以讓我們看看每一行,它的成本:

sum = 0 
i = 1 
# [...] 
return sum 

那些有明顯固定的時間,L. 的獨立的在循環中,我們有:

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 

多少次循環是否執行? 它obvously依賴於L. 的大小允許呼叫loops(L)

所以我們得到的

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

的整體複雜身爲好人的我,我會告訴你該列表查找在蟒蛇恆定的,所以把它歸結爲

O(loops(L))(忽略常數因子,如大O約定暗示)

你的循環次數是多少次,基於的L? (a)與列表中的項目一樣,列表中的項目(b)的數量與列表中的項目數量一樣多(?)。

(c)由於列表中的項目(d)比(b)更頻繁,因此次數更少?

+1

好重寫!我提高了這一點。希望@ovgolovin可以看到前一個和作業問題的質量之間的區別。我覺得我對最新版本的評論非常相關。 – jdi 2012-04-23 20:46:22

+0

好的答案,順便說一下! +1 – ovgolovin 2012-04-23 20:54:56

+0

@jdi是的,但是因爲它並不真正破壞OP,我只是恢復了我的第一個答案,所以我們在這裏有一個簡短的答辯答案;)(並且不要將您對該答案的評論掩埋) – ch3ka 2012-04-23 21:02:13

9

我不是計算機專業的,我不要求有這種理論的強抓,但我想這可能是相關的人從我的角度,試圖促成一個答案。

你的函數總是需要時間來執行,如果它是在不同長度的list參數運行,那麼所花費的時間來運行該功能會相對多少元素在該列表中。

讓我們假設處理一個長度爲== 1的列表需要1個單位的時間。問題的問題是列表的大小與此函數執行時間的增加之間的關係變大。

此鏈接打破了大O記法的一些基本知識:http://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/

如果是O(1)複雜性(這是不是真正的你的AD選項之一),那麼這將意味着複雜性永不不管大小L.顯然在你的例子中,它正在做一個while循環,依賴於增長一個與L的長度相關的計數器i。我將集中討論i正在倍增的事實,以指示它將花費多長時間通過while循環和L的長度。基本上,試着比較while循環需要在len(L)的各個值上執行多少個循環,然後這將決定你的複雜性。 1個單位的時間可以通過while循環迭代1次。

希望我做出某種形式的貢獻在這裏,就這個問題我自己的專業知識的缺乏。

更新
澄清基於從ch3ka的評論,如果你做的比你現在有你的with循環中更多的,那麼你也將不得不考慮每個循環增加了複雜性。但是,因爲你的list lookup L[i] is constant complexity,跟隨它的數學,我們可以忽略這些複雜性。

+0

非常好的答案。但對我而言,它缺乏查找列表成本的事實。這可能是相關的。當然,我們在這裏只討論cpython。另一個python實現可能會改變結果,因爲列表查找實際上可能需要很長時間。 – ch3ka 2012-04-23 23:39:57

+0

@ ch3ka:列表查找是O(1)http://wiki.python.org/moin/TimeComplexity – jdi 2012-04-24 00:28:45

+0

當然是jdi。但是從你的回答中是不清楚的。 – ch3ka 2012-04-24 00:42:18

4

這裏找出一個快速和骯髒的方式:

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() 

...這會導致

plot of function loops vs parameter size

橫軸爲L的大小,縱軸是多少乘以函數循環;大O應該是非常明顯的。

+1

這似乎是正確的,因爲列表查找是'O(1)',正如ch3ka指出的那樣。更一般地說,這不是我們需要測量的迭代次數,而是時間。不過,它可以直接測量並用'matplotlib'繪製。 – 2012-04-23 20:13:57

+0

因爲列表查找是O(1),所以我們可以假設迭代次數爲〜=所花費的時間。這個問題也是關於名單的。 – g19fanatic 2012-04-23 20:15:46

+2

@ g19fanatic這是對的,但OP可能不知道這個事實,所以我認爲值得指出這種微妙的差異。這是邏輯中隱含的一步,我想變得更加明確,就是這樣。 – 2012-04-23 20:17:56

0

O(log(len(L))),如列表查找是一個常數時間的操作,該列表的大小無關。

+2

它的功課。不要給他答案。教。 – jdi 2012-04-23 20:13:18

+1

它沒有被標記爲:(現在是這樣,但爲了挽救我的屁股:這不是答案,他仍然需要閱讀大O符號;) – ch3ka 2012-04-23 20:14:50

+0

它在評論中被提出並在最近被標記。但是,家庭作業問題很難回答,因爲我們希望他們在不給他們數據的情況下學習。 – jdi 2012-04-23 20:15:46

2

當您查看該函數時,您必須確定列表大小將如何影響將發生的循環數。

在您的具體情況中,讓n增加並查看while循環將運行多少次。

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 

查看模式?現在回答你的問題,不是:

(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. 

結帳Hugh的答案實證結果:)

+0

當n是1時,爲什麼循環會運行一次?因爲分配爲1的i不小於1(因此它們相等)的len(L)。這是不是意味着它會跳過while循環並直接返回總和,即0? – alicew 2012-04-23 22:20:32

+0

你有'而我 g19fanatic 2012-04-23 22:35:59

3

考慮與長度的輸入N = 10會發生什麼。現在考慮如果輸入大小增加到20倍會發生什麼情況。運行時也會增加兩倍嗎?然後它是線性的。如果運行時間增長了4倍,那麼它是二次的。等