時間複雜度怎麼算?如何計算時間複雜度?

知亦行發表於2019-07-24
   ⑴ 找出演算法中的基本語句;
 
  演算法中執行次數最多的那條語句就是基本語句,通常是最內層迴圈的迴圈體。
 
  ⑵ 計算基本語句的執行次數的數量級;
 
  只需保留f(n)中的最高次冪正確即可,可以忽略所有低次冪和最高次冪的係數。
 
  ⑶ 用大Ο記號表示演算法的時間效能。
 
  將基本語句執行次數的數量級放入大Ο記號中。
 
  如果演算法中包含巢狀的迴圈,則基本語句通常是最內層的迴圈體,如果演算法中包含並列的迴圈,則將並列迴圈的時間複雜度相加。例如:
 
  for (i=1; i<=n; i++)
  x++;
 
  for (i=1; i<=n; i++)
    for (j=1; j<=n; j++)
      x++;
 
  第一個for迴圈的時間複雜度為Ο(n),第二個for迴圈的時間複雜度為Ο(n²),則整個演算法的時間複雜度為Ο(n+n²)=Ο(n²)。
  注、加法原則:T(n)=O(f(n))+O(g(n))=O(max(fn,gn))
 
  常見的演算法時間複雜度由小到大依次為:
 
  Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n²)<Ο(n³)<…<Ο(2^n)<Ο(n!)<O(n^n)
 
Ο(1)表示基本語句的執行次數是一個常數,一般來說,只要演算法中不存在迴圈語句,其時間複雜度就是Ο(1)。Ο(log2n)、Ο(n)、Ο(nlog2n)、Ο(n2)和Ο(n3)稱為多項式時間,而Ο(2n)和Ο(n!)稱為指數時間。電腦科學家普遍認為前者是有效演算法,把這類問題稱為P類問題,而把後者稱為NP問題。
 
 
 
對於一個迴圈,假設迴圈體的時間複雜度為 O(n),迴圈次數為 m,則這個迴圈的時間複雜度為 O(n×m)。
 
void aFunc(int n) {

  for(int i = 0; i < n; i++) { // 迴圈次數為 n

  printf("Hello, World!\n"); // 迴圈體時間複雜度為 O(1)

  }
}

 

此時時間複雜度為 O(n × 1),即 O(n)。

對於多個迴圈,假設迴圈體的時間複雜度為 O(n),各個迴圈的迴圈次數分別是a, b, c...,則這個迴圈的時間複雜度為 O(n×a×b×c...)。分析的時候應該由裡向外分析這些迴圈。

void aFunc(int n) {
    for(int i = 0; i < n; i++) { // 迴圈次數為 n
        for(int j = 0; j < n; j++) { // 迴圈次數為 n
            printf("Hello, World!\n"); // 迴圈體時間複雜度為 O(1)
        }
    }
}                

 

此時時間複雜度為 O(n × n × 1),即 O(n^2)。

 

對於順序執行的語句或者演算法,總的時間複雜度等於其中最大的時間複雜度。

void aFunc(int n) {
// 第一部分時間複雜度為 O(n^2)
for(int i = 0; i < n; i++) {
  for(int j = 0; j < n; j++) {
    printf("Hello, World!\n");
  }
}
// 第二部分時間複雜度為 O(n)
for(int j = 0; j < n; j++) {
  printf("Hello, World!\n");
}
}

 

此時時間複雜度為 max(O(n^2), O(n)),即 O(n^2)。

對於條件判斷語句,總的時間複雜度等於其中 時間複雜度最大的路徑 的時間複雜度。

void aFunc(int n) {
if (n >= 0) {
// 第一條路徑時間複雜度為 O(n^2)
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
printf("輸入資料大於等於零\n");
}
}
} else {
// 第二條路徑時間複雜度為 O(n)
for(int j = 0; j < n; j++) {
printf("輸入資料小於零\n");
}
}
}

 

此時時間複雜度為 max(O(n^2), O(n)),即 O(n^2)。

時間複雜度分析的基本策略是:從內向外分析,從最深層開始分析。如果遇到函式呼叫,要深入函式進行分析。

相關文章