關於**的時間複雜度,我們可能在 大學裡 的計算機基礎、 資料結構、 演算法導論 等一系列的課程中,學習或接觸過。幾乎所有計算機系 或 數學計算機系的 都對它們很熟悉,沒一門語言都不會逃過時間複雜度,這個說起來算是非常基礎的知識點了,那我為什麼還要拿到高階裡面來說呢,因為日常中的 剛剛入門的 pythoner或者非科班出身的程式設計師 很少注意他們編寫的程式時間複雜度,掌握好時間複雜度是掌握演算法的很重要的因素,因為演算法初衷就在於降低時間複雜度。
本篇使用 大o計數法來描述時間複雜度,引用維基百科的描述:
下面我會通過一些例子來舉證它的時間複雜度:
def linear_search(l, x): # 線性搜尋 列表的長度是決定性因素 o(len(l))
for e in l:
if e == x:
return true
return false
線性搜尋的時間複雜度o(n),取決於列表的長度,在時間複雜度上來說它是一種優秀複雜度,因為隨著列表的增長,時間複雜度不會出現**性的增長。
def fact(n):
answer = 1 # 1
while n > 1: # 5 *n
answer *= n
n -= 1
return answer # 1 所有 5n + 2
看到上面的**, answer賦值的時候進行了一步操作, 隨後的while迴圈裡,進行了5步操作,迴圈的時間複雜度取決於 n的大小,所以是5n, 最後return 又是一步操作,所以總的步數為5n+2,仔細算的是這樣,但在大o表示法裡,是忽略常數的(大o表示法通常會忽略常數,因為它關注的是演算法的消耗時間隨著n的變化而怎麼變化,這樣算有沒有弊端呢,有的,就是某些情況下使用大o表示法的時間複雜度是一致的,但實際上是有差異的),所以如果用大o來表示的話,為o(n)。
def factor(n): # 階乘 o(n) 遞迴
if n == 1:
return 1
else:
return n * factor(n-1)
這段階乘的**,時間複雜度為o(n)
def sqrt_bi(x, eps): # 2分查詢 30次
low = 0.0
high = max(1, x)
ans = (high + low) / 2.0
while abs(ans**2 - x) == eps:
if ans**2 == x:
low = ans
else:
high = ans
ans = (high + low) / 2.0
return ans
上面這段**,是用python實現的二分查詢,它的的時間複雜度用大o表示法表述為為o(log(n))
def sqrt_exhaust(x, eps):
step = eps ** 2 # 2
ans = 0.0 # 1
while abs(ans**2 - x) >= eps and ans <= max(x, 1): # 8 * 迴圈執行的次數
ans += step
return ans # 1 所有 3 + 8 * 迴圈執行次數
這兩段**的作用是相同的,但兩種方法 輸入100到最後求得結果0.0001 乙個迴圈要花費 8000000 次 (第二種)乙個只需要迴圈30次(第一種),當然這是演算法的問題,只不過體現的是時間複雜度,當你掌握了時間複雜度後,你才會去考慮演算法的優劣性。
def is_subset(l1, l2): # 多項式 o(len(l1) * len(l2))
for e1 in l1:
matched = false
for e2 in l2:
if e1 == e2:
matched = true
break
if not matched:
return false
return true
上面這段**,演算法執行時間會成二次方的增長,理論上來說,這是相當糟糕的時間複雜度了,但這樣**在新手裡,是非常常見的,我本人初期就寫過很多這樣的**。
def get_subsets(l): # 指數演算法 漢諾塔 o(2^n)
if len(l) == 0:
return
smaller = get_subsets(l[:-1])
extra = l[-1:]
new =
for small in smaller:
return smaller + new
在這段漢諾塔**裡,並不是平常見到的漢諾塔的寫法,演算法的執行時間會成2的n次方增長,實際上是糟糕的時間複雜度了。
在日常的生產活動中,我們應該竭力尋找時間複雜度小的演算法,如 線性時間,掌握了時間複雜度有助於你寫出或找到更好的演算法,選擇好的演算法也是效能優化的一部分。
python高階學習chapter03(迭代相關)
重要概念!迭代器,可迭代物件,生成器,很容易繞暈了。凡是可以使用for進行迴圈的就是可迭代物件,其中可以通過next方法逐步輸出的就是迭代器,生成器的形成有兩種 一種是把列表生成式改成 一種是帶有yield語句的。具體的可以看 接下來進入主題 如何實現乙個迭代器?實現乙個迭代器 from colle...
C 高階程式設計 Chapter2
預定義資料型別 值型別 和 引用型別 引用型別 指向包含物件的記憶體位置 decimal 128 位精度 十進位制數表示法 不是基本資料型別,會有效能損失,專用於財務計算 byte 8 short 16 int 32 long 64 float 32位精度 double 64位精度 char 16位...
UNIX 環境高階程式設計Chapter 1 2
第一條規則是 如果沒有出錯,則其值不會被乙個例程清除。因此,僅當函式的返回值指明出錯時,才檢驗其值。第二條是 任一函式都不會將 e r r n o值設定為0,在 e r r n o h 中定義的所有常數都不為 0。c標準定義了兩個函式,它們幫助列印出錯資訊。include c h a r s t r...