時間複雜度的意義算法
究竟什麼是時間複雜度呢?讓咱們來想象一個場景:某一天,小灰和大黃同時加入了一個公司......編程
一天事後,小灰和大黃各自交付了代碼,兩端代碼實現的功能都差很少。大黃的代碼運行一次要花100毫秒,內存佔用5MB。小灰的代碼運行一次要花100秒,內存佔用500MB。因而......函數
因而可知,衡量代碼的好壞,包括兩個很是重要的指標:spa
1.運行時間;翻譯
2.佔用空間。code
基本操做執行次數內存
關於代碼的基本操做執行次數,咱們用四個生活中的場景,來作一下比喻:get
場景1:給小灰一條長10寸的麪包,小灰每3天吃掉1寸,那麼吃掉整個麪包須要幾天?數學
答案天然是 3 X 10 = 30天。string
若是麪包的長度是 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,執行次數是線性的。
場景2:T(n) = 5logn,執行次數是對數的。
場景3:T(n) = 2,執行次數是常量的。
場景4:T(n) = 0.5n^2 + 0.5n,執行次數是一個多項式。
漸進時間複雜度
有了基本操做執行次數的函數 T(n),是否就能夠分析和比較一段代碼的運行時間了呢?仍是有必定的困難。
好比算法A的相對時間是T(n)= 100n,算法B的相對時間是T(n)= 5n^2,這兩個到底誰的運行時間更長一些?這就要看n的取值了。
因此,這時候有了漸進時間複雜度(asymptotic time complectiy)的概念,官方的定義以下:
若存在函數 f(n),使得當n趨近於無窮大時,T(n)/ f(n)的極限值爲不等於零的常數,則稱 f(n)是T(n)的同數量級函數。
記做 T(n)= O(f(n)),稱O(f(n)) 爲算法的漸進時間複雜度,簡稱時間複雜度。
漸進時間複雜度用大寫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)< O(logn)< O(n)< O(n^2)
在編程的世界中有着各類各樣的算法,除了上述的四個場景,還有許多不一樣形式的時間複雜度,好比:
O(nlogn), O(n^3), O(m*n),O(2^n),O(n!)
從此遨遊在代碼的海洋裏,咱們會陸續遇到上述時間複雜度的算法。
時間複雜度的巨大差別
咱們來舉過一個栗子:
算法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則愈來愈慢,差距愈來愈明顯。
這就是不一樣時間複雜度帶來的差距。