複雜度

Complexity

目錄

定義/概念

Definition

程式的好壞

一份程式的好壞有很多面向

  • 運行時間
  • 占用記憶體
  • 可讀性

如何評估?

運行時間

手動計時 / 引用時間函式庫進行測量?

import time

time_start = time.time()
# 執行程式
time_end = time.time()

print(time_end - time_start)

變因過多(電腦效能等)

需要實際測量才能得知

運行時間

假設「基礎運算」運行時間為一單位時間

a = 1;
a += 3;
  • 宣告 = 賦值 = 運算 ... 皆為一單位時間

將時間表示成相關因素(e.g. 輸入量)的函數 T(n)

  • 對「基礎運算」的定義?
  • 程式很長?

粗略估計

考慮將 T(n) 以更簡單的方式描述

  • 將 T(n) 分類
  • n 足夠大時,兩個函式有差不多的趨勢
    • n 很大時,運行時間比值是一個常數
\lim\limits_{x\to\infty}\frac{f(x)}{g(x)} = C
  • 數學

範例

  • 顯然我們有                                       同一類
  • 一樣顯然                                                  同類
  •                                          同類?
  • 換個更精確的說法,   的級別小於或等於
  • 幫這些類別取名
f(n) = 2,\ g(n) = 1
f(n)=2n+1,\ g(n)=n
f(n)=n,\ g(n)=n^2
f
g

大O符號

  • 規範一個集合,將所有符合       的函數    規範在                 內
  •  
  • 用等於不用屬於也行
  • 規範了函數的上界
  • 忽略係數、「剩餘項」作為代表
f
O(g(x))
f(x)\in O(g(x))
\lim\limits_{x\to\infty}\frac{f(x)}{g(x)} = C

什麼是剩餘項?

讓我們開啟 Geogebra 來觀察一下

x^2\\ x \\ log(x) \\ 2^x \\ x\ log(x) \\ x!

它們在 x 很大時的表現如何

所以,省略剩餘項?

  • 在函數中,每一項可以依照大小關係排序
  • 在 大 O 記號 中,我們只保留最大的那項
  • 記得忽略前面的係數

複雜度

  • 歸納函數類別的方法應用在分析程式上,將 T(n) 歸類,就可以將程式的時間和資料關係歸納出來
  • 歸納方法不同符號不同,常見的還有
  • 提供程式運行時間、空間等估計的依據
\Theta

分析方法

Algorithm Analysis

複雜度分析

  • 「抓個大概就好」
  • 分析的過程可以忽略最高項以外的其他項
  • 常見複雜度:
  • 常數時間
  • 對數時間
  • 線性時間
  • 線性對數時間
  • 各種冪次
  • 指數時間
O(1)
O(log\ n)
O(n)
O(n\ log\ n)
O(n^2),\ O(n^3)...
O(2^n),\ O(3^n)...

練習

a = 0

for i in range(1, n + 1):
  a += i

print(a)

練習

a = 0

for i in range(1, 2 * n + 1):
  a += i

print(a)

練習

a = a * (a + 1) // 2

print(a)

練習

a = n
while a != 1:
  a //= 2

@演算法放課社員

def fast_pow(a: int, n: int) -> int:
    if n == 0:
      return 1
    
    temp = fast_pow(a, n // 2)
    
    if n % 2 == 0:
        return temp * temp
    else
        return a * temp * temp

@通靈

a = int(input())
n = int(input())
print(a ** n)

@通靈

a = float(input())
n = float(input())
print(a ** n)

一般來說, C++ 每秒可以跑 1e8 ~ 1e9 (約 3e8)

Python 可能 1e7 或以下(?

常見複雜度對應到時限一秒

複雜度 範圍
10~12
20~23
24~28
500~600
5000~6000
5e3~1e4
O(n!)
O(2^n)
O(n2^n)
O(n^3)
O(n^2log\ n)
O(n^2)
複雜度 範圍
1e5~5e5
5e5~6e5
1e6~2e6
          (輸入) 1e6~1e7
          (不含) 1e7~3e8
1e18
O(n\ log^2n)
O(n)
O(n\ log\ n)
O(n\sqrt n)
O(n)
O(log\ n)

實際上因為常數關係,經驗成分居多(

一些延伸

理論計算機科學

計算複雜性理論

P/NP 問題 維基中文翻得有點爛

Made with Slides.com