首頁  >  文章  >  後端開發  >  資料結構之一組圖讓你搞懂時間複雜度

資料結構之一組圖讓你搞懂時間複雜度

little bottle
little bottle轉載
2019-04-28 12:01:352168瀏覽

 這篇文章中透過一組圖片讓你輕鬆明白什麼是時間複雜度,有趣生動,具有一定學習價值,有興趣的朋友快來了解一下吧。

資料結構之一組圖讓你搞懂時間複雜度

資料結構之一組圖讓你搞懂時間複雜度

資料結構之一組圖讓你搞懂時間複雜度

資料結構之一組圖讓你搞懂時間複雜度

資料結構之一組圖讓你搞懂時間複雜度

資料結構之一組圖讓你搞懂時間複雜度

 資料結構之一組圖讓你搞懂時間複雜度

#時間複雜度的意義

 

資料結構之一組圖讓你搞懂時間複雜度究竟什麼是時間複雜度呢?讓我們來想像一個場景:某一天,小灰和大黃同時加入了一個公司......

資料結構之一組圖讓你搞懂時間複雜度#一天過後,小灰和大黃各自交付了程式碼,兩端程式碼實現的功能都差不多。大黃的程式碼運行一次要花100毫秒,記憶體佔用5MB。小灰的程式碼運行一次要花100秒,記憶體佔用500MB。於是......

資料結構之一組圖讓你搞懂時間複雜度

由此可見,衡量程式碼的好壞,包括兩個非常重要的指標:

1.運行時間;

資料結構之一組圖讓你搞懂時間複雜度2.佔用空間。

資料結構之一組圖讓你搞懂時間複雜度

 資料結構之一組圖讓你搞懂時間複雜度

#基本運算執行次數

 

關於程式碼的基本運算執行次數,我們用四個生活中的場景,來做一下比喻:

場景1 :資料結構之一組圖讓你搞懂時間複雜度給小灰一條長10寸的麵包,小灰每3天吃掉1寸,那麼吃掉整個麵包需要幾天?

答案自然是 3 X 10 = 30天。

如果麵包的長度是 N 吋呢?

此時吃掉整個麵包,需要 3 X n = 3n 天。

如果用一個函數來表示這個相對時間,可以記作 T(n) = 3n。

場景2:

給小灰一條長16寸的麵包,小灰每5天吃掉麵包剩餘長度的一半,第一次吃掉8寸,第二次吃掉4寸,第三次吃掉2寸......那麼小灰把麵包吃得只剩下1寸,需要多少天呢?

這個問題翻譯一下,就是數字16不斷除以2,除幾次以後的結果等於1?這裡要牽涉到數學當中的對數,以2位底,16的對數,可以簡寫為log16。

因此,把麵包吃得只剩下1寸,需要 5 X log16 = 5 X 4 = 20 天。

如果麵包的長度是 N 吋呢?

需 5 X logn = 5logn天,記作 T(n) = 5logn。

場景3:資料結構之一組圖讓你搞懂時間複雜度給小灰一條長10吋的麵包和一隻雞腿,小灰每2天吃掉一隻雞腿。那麼小灰吃掉整個雞腿需要多少天呢?

答案自然是2天。因為只說是吃掉雞腿,跟10吋的麵包沒有關係 。

如果麵包的長度是 N 吋呢? ######無論麵包多長,吃掉雞腿的時間還是2天,記作 T(n) = 2。 ###

場景4:給小灰一條長10吋的麵包,小灰吃掉第一個一吋需要1天時間,吃掉第二個一吋需要2天時間,吃掉第三個一寸需要3天時間.....每多吃一寸,所花的時間也多一天。那麼小灰吃掉整個麵包需要多少天呢?

答案是從1累加到10的總和,也就是55天。

如果麵包的長度是 N 吋呢?

此時吃掉整個麵包,需要 1 2 3 ...... n-1 n = (1 n)*n/2 = 0.5n^2 0.5n。

記作 T(n) = 0.5n^2 0.5n。

資料結構之一組圖讓你搞懂時間複雜度

上面所講的是吃東西所花費的相對時間,這一想法同樣適用於對程式基本運算執行次數的統計。剛才的四個場景,分別對應了程式中最常見的四種執行方式:

場景1:T(n) = 3n,執行次數是線性的。

void eat1(int n){
    for(int i=0; i<n; i++){;
        System.out.println("等待一天");
        System.out.println("等待一天");
        System.out.println("吃一寸面包");
    }
}
vo

場景2:T(n) = 5logn,執行次數是對數的。

void eat2(int n){
   for(int i=1; i<n; i*=2){
       System.out.println("等待一天");
       System.out.println("等待一天");
       System.out.println("等待一天");
       System.out.println("等待一天");
       System.out.println("吃一半面包");
   }
}

場景3:T(n) = 2,執行次數是常數的。

void eat3(int n){
   System.out.println("等待一天");
   System.out.println("吃一个鸡腿");
}

場景4:T(n) = 0.5n^2 0.5n,執行次數為多項式。

void eat4(int n){
   for(int i=0; i<n; i++){
       for(int j=0; j<i; j++){
           System.out.println("等待一天");
       }
       System.out.println("吃一寸面包");
   }
}

 

資料結構之一組圖讓你搞懂時間複雜度

#漸進時間複雜度

## 

資料結構之一組圖讓你搞懂時間複雜度

資料結構之一組圖讓你搞懂時間複雜度

##有了基本操作執行次數的函數T(n),是否就可以分析比較一段程式碼的運行時間了呢?還是有一定的困難。

例如演算法A的相對時間是T(n)= 100n,演算法B的相對時間是T(n)= 5n^2,這兩個到底誰的運行時間更長一些?這就要看n的值了。

所以,這時候有了漸進時間複雜度(asymptotic time complectiy)的概念,官方的定義如下:
  1. 若存在函數f(n),使得當n趨近於無窮大時,T(n)/ f(n)的極限值為不等於零的常數,則稱f(n)為T(n)的同數量級函數。

    記作 T(n)= O(f(n)),稱O(f(n)) 為演算法的漸進時間複雜度,簡稱時間複雜度。
  2. 漸進時間複雜度用大寫O來表示,所以也稱為大O表示法。

如何推導出時間複雜度呢?有以下幾個原則:

如果運行時間是常數級,用常數1表示;

只保留時間函數中的最高階項;

如果最高階項存在,則省去最高階項前面的係數。

資料結構之一組圖讓你搞懂時間複雜度

讓我們回頭看看剛才的四個場景。

場景1:

T(n) = 3n 

最高階項為3n,省去係數3,轉換的時間複雜度為:資料結構之一組圖讓你搞懂時間複雜度

T(n) =  O(n)

#場景2:

T (n) = 5logn 

最高階項為5logn,省去係數5,轉換的時間複雜度為:資料結構之一組圖讓你搞懂時間複雜度

T(n) =  O(logn)

場景3:

T(n) = 2

只有常數量級,轉換的時間複雜度為:資料結構之一組圖讓你搞懂時間複雜度

T(n) =  O(1)

#「場景4:

T(n) = 0.5n^ 2 0.5n

最高階項為0.5n^2,省去係數0.5,轉換的時間複雜度為:資料結構之一組圖讓你搞懂時間複雜度

T(n) =  O(n^2)

#########這四種時間複雜度究竟誰用時更長,誰節省時間呢?稍微思考一下就可以下結論:######O(1)資料結構之一組圖讓你搞懂時間複雜度

時間複雜度的巨大差異

資料結構之一組圖讓你搞懂時間複雜度

資料結構之一組圖讓你搞懂時間複雜度

我們來舉過一個栗子:

演算法A的相對時間規模是T(n)= 100n,時間複雜度是O(n)

演算法B的相對時間規模是T(n)= 5n^2,時間複雜度是O(n^2)

演算法A運行在小灰家裡的老舊電腦上,演算法B運行在某台超級電腦上,運轉速度是老舊電腦的100倍。

那麼,隨著輸入規模 n 的成長,兩個演算法誰運行得更快呢?

資料結構之一組圖讓你搞懂時間複雜度

從表格中可以看出,當n的值很小的時候,演算法A的運行用時要遠大於演算法B;當n的值達到1000左右,演算法A和演算法B的運行時間已經接近;當n的值越來越大,達到十萬、百萬時,演算法A的優勢開始顯現,演算法B則越來越慢,差距越來越明顯。

這就是不同時間複雜度所帶來的差距。

資料結構之一組圖讓你搞懂時間複雜度

想了解更多技術教程,請一定關注PHP中文網哦!

以上是資料結構之一組圖讓你搞懂時間複雜度的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除