1. 程式人生 > >如何計算時間複雜度--及其分析

如何計算時間複雜度--及其分析

原地址:http://www.nowamagic.net/librarys/veda/detail/2195

在進行演算法分析時,語句總的執行次數T(n)是關於問題規模n的函式,進而分析T(n)隨n的變化情況並確定T(n)的數量級。演算法的時間複雜度,也就是演算法的時間量度,記作:T(n}=0(f(n))。它表示隨問題規模n的增大,演算法執行時間的埔長率和 f(n)的埔長率相同,稱作演算法的漸近時間複雜度,簡稱為時間複雜度。其中f( n)是問題規橫n的某個函式。

  • 這樣用大寫O()來體現演算法時間複雜度的記法,我們稱之為大O記法。一般情況下,隨著n的增大,T(n)增長最慢的演算法為最優演算法。

  • 之前我們說的三個求和演算法的時間複雜度分別為0(n),0(1),0(n2)。我就推一下吧。

  • 計算 1 + 2 + 3 + 4 + ...... + 100。程式碼如下,之前也有講過:

  • #include "stdio.h"
     
    int main()
    {
        int i, sum = 0, n = 100;	/* 執行1次 */
        for( i = 1; i <= n; i++)	/* 執行 n+1 次 */
        {
            sum = sum + i;			/* 執行n次 */
            //printf("%d \n", sum);
        }
        printf("%d", sum);			/* 執行1次 */
    }
    

     

    • 從程式碼附加的註釋可以看到所有程式碼都執行了多少次。那麼這寫程式碼語句執行次數的總和就可以理解為是該演算法計算出結果所需要的時間。該演算法所用的時間(演算法語句執行的總次數)為: 1 + ( n + 1 ) + n + 1 = 2n + 3

      而當 n 不斷增大,比如我們這次所要計算的不是 1 + 2 + 3 + 4 + ...... + 100 = ? 而是 1 + 2 + 3 + 4 + ...... + n = ?其中 n 是一個十分大的數字,那麼由此可見,上述演算法的執行總次數(所需時間)會隨著 n 的增大而增加,但是在 for 迴圈以外的語句並不受 n 的規模影響(永遠都只執行一次)。所以我們可以將上述演算法的執行總次數簡單的記做: 2n 或者簡記 n

      這樣我們就得到了我們設計的演算法的時間複雜度,我們把它記作: O(n)

      再來看看高斯的演算法:

    • #include "stdio.h"
       
      int main()
      {
          int sum = 0, n = 100;	/* 執行1次 */
          sum = (1 + n) * n/2;	/* 執行1次 */
       
          printf("%d", sum);		/* 執行1次 */
      }
      

      這個演算法的時間複雜度: O(3),但一般記作 O(1)。

      從感官上我們就不難看出,從演算法的效率上看,O(3) < O(n) 的,所以高斯的演算法更快,更優秀。

      下面再來一個例子:

    • #include "stdio.h"
       
      int main()
      {
          int i, j, x = 0, sum = 0, n = 100;	/* 執行1次 */
          for( i = 1; i <= n; i++)
          {
              sum = sum + i;
              //printf("%d \n", sum);
              for( j = 1; j <= n; j++)
              {
                  x++;                /* 執行n*n次 */
                  sum = sum + x;
              }
          }
          printf("%d", sum);			/* 執行1次 */
      }
      

      上面的程式碼嚴格的說不能稱之為一個演算法,畢竟它很“無聊而且莫名其妙”(畢竟演算法是為了解決問題而設計的嘛),先不論這個“演算法”能解決什麼問題,我們看一下它的“大O階”如何推導,還是先計算一下它的執行總次數:

      執行總次數 = 1 + (n + 1) + n*(n + 1) + n*n + (n + 1) + 1 = 2n2 + 3n + 3

      如何推導大o階呢?我們給出了下面 的推導方法:

    • 用常數1取代執行時間中的所有加法常數。
    • 在修改後的執行次數函式中,只保留最髙階項。
    • 如果最高階項存在且不是1,則去除與這個項相乘的常數
    • 第三步:“如果最高階項存在且不是 1 ,則去除與這個項相乘的常數”。這裡 n 的二次方不是 1 所以要去除這個項的相乘常數,算式變為:執行總次數 = n^2

      因此最後我們得到上面那段程式碼的演算法時間複雜度表示為: O( n^2 )

      按照上面推導“大O階”的步驟我們先來第一步:“用常數 1 取代執行時間中的所有加法常數”,則上面的算式變為:執行總次數 = 2n^2 + 3n + 1

      第二步:“在修改後的執行次數函式中,只保留最高階項”。這裡的最高階是 n 的二次方,所以算式變為:執行總次數 = 2n^2