1. 程式人生 > 其它 >漸進時間複雜度

漸進時間複雜度

漸進時間複雜度

\(T(n)\)

\(T(n)\)是一個演算法所需的基本操作的次數,通常是在RAM計算模型下的基本操作。

三種漸進複雜度

  • \(O\)記號:最壞情況估計
    \(T(n) = O(f(n))\ \ iff\ \exist c>0,當n>>2後,有T(n)\color{red}{<}c\cdot f(n)\)
    例:\(\sqrt{5n\cdot [3n\cdot (n+2)+4]+6}<\sqrt{5n\cdot [6n^2+4]+6}<\sqrt{35n^3+6}<6\cdot n^{1.5}=O(n^{1.5})\)

    • \(T(n)相比,f(n)更為簡潔,但是依然能反應前者的增長趨勢\)
      • 常係數可以忽略:\(O(f(n))=O(c\dot f(n))\)
      • 低次項可以忽略:\(O(n^a+n^b)=O(n^a),a>b>0\)
  • \(\Omega\)記號:最好情況估計
    \(T(n) = O(f(n))\ \ iff\ \exist c>0,當n>>2後,有T(n) \color{red}{>}c\cdot f(n)\)

  • \(\Theta\)記號:準確估計
    \(T(n) = O(f(n))\ \ iff\ \exist c_1>c_2>0,當n>>2後,有c_1\cdot f(n) {>} T(n) {>}c_2\cdot f(n)\)

常用的時間複雜度

高效解【很好】

常數複雜度\(O(1)\)

\(a=b=2022=2022\cdot 2022 = O(1)\)

對數複雜度\(O(logn)\)

\( 常底數無所謂:\forall a,b>0,log_an=log_ab\cdot log_bn=\Theta(log_bn)\\ 常數次冪無所謂:\forall c>0,logn^c=c\cdot logn=\Theta(logn)\\ 對數多項式:123\cdot log^{123}n+log^{107}(n^2-n+1)=\Theta(log^{123}n)\\ 這類演算法非常有效,時間複雜度趨於常數,複雜度低於任意多項式:\forall c>0,logn = O(n^c) \)

有效解【可以接受】

多項式複雜度$O(n^c)

\(a_{k}n^{k}+a_{k-1}n^{k-1}+\dots +a_1n+a_0=O(n^k)\),低次項都可以忽略

難解【難以接受】

指數複雜度\(O(2^n)\)

\(T(n)=a^n\\ \forall c>1,n^c=O(2^n),即任何多項式都被指數函式覆蓋 \)

演算法分析

\(演算法分析的兩個主要任務 = 正確性(不變性 \times 單調性) + 複雜度\)

正確性分析

不變性:每一次操作擁有的不變的性質
單調性:問題規模不斷減少

複雜度分析

主要工具

  • 迭代:級數求和
  • 遞迴:遞迴跟蹤 + 遞迴方程
  • 猜想 + 驗證

級數

  • 算術級數
\[T(n)=1+2+\dots + n = n(n+1)/2=O(n^2) \]
  • 冪方級數:比冪次高處一階
\[\sum^n_{k=0} k^d \approx \int^n_0 x^{d}dx=\frac{1}{d+1} x^{d+1}|^n_0 = \frac{1}{d+1} n^{d+1} =O(n^{d+1})\\ T_2(n)=1^2+2^2+3^2+\dots +n^2 = O(n^3)\\ T_3(n)=1^3+2^3+3^3+\dots +n^3 = O(n^4)\\ T_4(n)=1^4+2^4+3^4+\dots +n^4 = O(n^5)\\ \dots \]
  • 幾何級數:(a>1) 與末項同階
\[T_a(n) = a^0 + a^1 + \dots + a^n = \frac{a^{n+1}-1}{a-1} = O(a^n) \]
  • 收斂級數:都是O(1)
    級數如果收斂那麼其漸進複雜度就是\(O(1)\)
    e.g.幾何分佈$$(1-\lambda)[1\lambda +2\lambda^2 +3\lambda^3+ 4\lambda^4+ \dots ]=\frac{1}{1-\lambda}=O(1),0<\lambda<1$$
  • 不收斂但是長度有限的級數
    • 調和級數\[h(n)=1+1/2+1/3+\dots +1/n = \Theta(logn) \]
    • 對數級數\[g(n)=log1+log2+\dots +logn=logn(n!)=\Theta(nlogn) \]

迴圈

  • 迴圈與級數
for(int i = 0; i < n; i++)
  for(int j = 0; j < n; j++)
    O(1)Operation(i,j);

\(T(n)=n+n+\dots +n=n*n=O(n^2)\)

2.

for(int i = 0; i < n; i++)
  for(int j = 0; j < i; j++)
    O(1)Operation(i,j);

\(T(n)=1+2+3+\dots +n=n*(n+1)/2=O(n^2)\)

3.

  for(int i = 0; i < n; i++)
    for(int j = 0; j < i; j+=2013)
      O(1)Operation(i,j);

\(T(n)=\dots\)僅僅是一個常係數優化

4.

  for(int i = 0; i < n; i <<= 1)
    for(int j = 0; j < i; j++)
      O(1)Operation(i,j);

\(T(n)=1+2+4+8+\dots+2^{\lfloor log_2(n-1) \rfloor} = 2^{\lceil log_2(n-1) \rceil} -1= O(n)\)

封底估算

時間估算

\[1天 \approx 10^5s\\ 100年 \approx 10^9s \]