# 複雜度 ## 12/15社課 --- ### 複雜度是啥 簡單來說就是 程式的好壞程度的量化 基本上以使用的時間和空間來作為標準 ---- ### 為什麼需要複雜度 如果你不希望寫出來的程式出現TLE ~~尤其是檢定剩5分鐘的情況下~~ 那就得在寫程式前評估做法 ---- ### 複雜度的概念 一次函數vs二次函數 y=x+10 、 y=x^2 在數字很大的時候 右式會大於左式很多 以多次執行而言 左式比較容易(量級低) ---- ### 量級 對於兩個數學式的比較而言 如果一個數學式的成長幅度較大(ex:曲線幅度) 則此數學式的量級較大 [參考圖](https://hackmd.io/_uploads/rkYPVT_Lp.png) --- ### 時間複雜度 指完全地執行程式所需的時間 通常以執行次數計算 ~~也就是萬惡TLE的根源~~ 表達方式為 Big O ---- ### 時間複雜度的表達 如果執行次數固定 不會因為輸入值而改變 這種情況被寫作 O(1) ```cpp= cin >> a; cout << a;//這裡只固定執行一次! ``` ---- O(n) 和 O(n^2) 如下 ```cpp= for(i=0;i<n;i++){ cout << i; } //O(n) for(i=0;i<n;i++){ for(i=0;i<n-1;i++){ //這裡執行了n*(n-1)次 cout << i; } } //O(n^2) ``` 時間複雜度取最高次方 其他 O(n log(n)) O(n^3) 只要大致上數迴圈數量就行 ---- ### 時間複雜度的計算 以最糟情況做計算 只考慮最高次方 省略係數 ---- 假設OJ 1秒能跑10^8次運算 把題目的n範圍帶入估算複雜度 並除以10^8 就能大致推算秒數 ---- Example: 1 < n < 5×10^5 ,O(n^2) 5×10^5 的平方除以10^8就是秒數 ---- 函數的複雜度不是只有O(1) 使用函數的時候要清楚它的執行時間 (像vector 的 insert() 和 erase()都不是O(1) ! ) ---- 另外 在函數中傳遞一個很大的物件時 由於函數的傳遞視作把整個物件複製一次 所以複雜度並不是O(1) --- ### 空間複雜度 字面上翻譯就是使用的空間量 也就是記憶體用量 表達方式也是 Big O ---- 這裡的變數使用量是固定不變的 記作O(1) ```cpp= cin >> n; for(int i=0;i<n;i++){ cout<<i; } ``` ---- 這裡的變數用量會隨輸入大小而增加 記作O(n) ```cpp= cin >> n; int A[n]; for(int i=0;i<n;i++){ A[n] = i; } ``` --- 時間和空間複雜度是能互相交換的 可以透過較多的記憶體用量換取時間 也就是 ~~以空間換時間~~ 如泡沫排序(時間久) 桶排序(記憶體用量大) 可以視情況使用適合的演算法 ---- 練習 [c296](https://zerojudge.tw/ShowProblem?problemid=c296)
{"contributors":"[{\"id\":\"f73e3593-2b30-4cf8-89e6-dc544aaab97d\",\"add\":1535,\"del\":41}]","title":"複雜度 Complexity"}
    182 views