# 複雜度 by : hush --- 如何判斷一個程式碼的效率呢? ---- 看它的執行的時間和使用的記憶體量多寡 也就是**時間複雜度**和**空間複雜度** --- ## 時間複雜度 ---- 我們先當作所有簡單運算的執行時間都一樣 * 加減乘除: $a+b$ * 取餘數: $a\% b$ * 位元運算: $a|b$ * 存取記憶體: $a[i]$ * 判斷運算子: $a\lt b$ * 賦值運算子: $a = b$ ---- 然後算出程式一共要執行幾次簡單運算 ---- 例如: ```cpp= int n; cin >> n; for (int i=0;i<n;i++) cout << "Hello World\n"; ``` ```cpp=3 //執行次數:n+2 ``` ```cpp= int n; cin >> n; for (int i=0;i<n;i++) { for (int i=0;i<n;i++) { cout << i << " : Hello World\n"; } } for (int i=n-1;i>=0;i--) cout << "Hello World\n"; ``` ```cpp=10 //執行次數:2n²+n+2 ``` ---- 但每次都要列出式子很麻煩 其實只要看影響最大的項就好了 這時就可以使用**Big-O**符號 ---- 可以忽略影響不大的首項係數和低次項,例如: * $3𝑛^3 + 5𝑛^2 + 10𝑛 + 3 = O(n^3)$ * $\tfrac{1}{10}𝑛^5 + 50𝑛^4 - 100𝑛 = O(n^5)$ * $888 = O(1)$ ---- 換你們了: * $7𝑛^2 + 5𝑛 -1000 = O(???)$ * ||$O(n^2)$|| * $2^n + n^3 = O(???)$ * ||$O(2^n)$|| * $\sum\limits_{k = 1}^n{\tfrac{n}{k}} = \tfrac{n}{1} + \tfrac{n}{2} + \dots + \tfrac{n}{n} = O(???)$ * ||$O(n\cdot ln(n)), ln=log_e$|| ---- 這些呢? ```cpp= for (int i=0;i<n;i++) for (int j=i-1;j>=0;j--) cout << '*' << " \n"[j==0]; ``` ||$O(n^2)$|| ```cpp= sort(a,a+n); ``` ||$O(nlogn)$|| ---- ```c= int f(int i) { if (i<2) return i; return f(i-1)+f(i-2); } main() { //it's C language int n,m; scanf("%d %d",&n,&m); printf("%d\n",f(n)-f(m)); } ``` ||$O(\phi ^n)\approx O(2^n)$|| --- ## 空間複雜度 ---- 跟時間複雜度類似 算出程式一共要開幾個空間 ---- 一樣也會用Big-O符號來表示複雜度 ---- 例如: ```cpp= int a[n]; //空間複雜度O(n) int a[n][m]; //空間複雜度O(n*m) long long a,b,c,d,e; //空間複雜度O(1) ``` --- ## 使用方法 ---- 先講**時間複雜度** ---- 一般的OJ一秒約可以跑$10^8$個簡單運算! 把數字帶入複雜度估算程式會不會超時 (寫久了會用數字推算複雜度) ---- 例如: * 複雜度是$O(n^2)$,題目說:$n\le 10^5$ $10^{5^2}=10^{10}\gt 10^8\implies$ TLE * 複雜度是$O(n^3)$,題目說:$n\le 10^2$ $10^{2^3}=10^{6}\lt 10^8\implies$ AC ---- 數字範圍與複雜度對應表 (多寫題目就記起來了) ![image](https://hackmd.io/_uploads/Bk1-PDF3C.png) ---- 接下來是**空間複雜度** ---- 基本上你陣列不開到超過$2\times 10^7$都會過 除了一些很搞的題目以外空間不太需要在意 ---- 因為電腦記憶體配置的[某些原因](https://sprout.tw/algo2024/homework/hand03.pdf) 陣列要開全域變數,不然有可能會報錯 ```cpp= #include<iostream> #define int long long #define colinorz cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); using namespace std; int a[100000]; signed main() { //colinorz; } ``` --- ## 總結 ---- 複雜度是解題最基本、最重要的部分 每一題都**必須**先算過複雜度再寫 ---- 所以請不要盲目地看到題目就開始寫 請先算過你寫出來的程式碼會過再寫 --- # 謝謝大家
{"title":"複雜度","description":"type : slide","contributors":"[{\"id\":\"b49547c8-0e7f-46d0-99b2-8a45dfee8e90\",\"add\":3224,\"del\":832}]"}
    143 views