算法的時間複雜度

前言

做爲一個非典型的前端開發人員,咱們要懂得一些算法的概念,並將其理論知識引入平常的開發中,提升平常的開發效率和提高產品的體驗。javascript

本篇博文的概念偏多,模糊的點,有興趣的谷歌起來啦!前端

相關概念

算法: 算法是指解題方案的準確而完整的描述,是一系列解決問腿的清晰指令,算法表明着用系統的方法描述解決問題的策略機制。java

算法的效率: 是指算法執行的時間,算法執行時間須要經過算法編制的程序在計算機上運行時所消耗的時間來衡量。git

一個算法的優劣能夠用空間複雜度時間複雜度來衡量。github

時間複雜度:評估執行程序所需的時間。能夠估算出程序對處理器的使用程度。算法

空間複雜度:評估執行程序所需的存儲空間。能夠估算出程序對計算機內存的使用程度。bash

算法設計時,時間複雜要比空間複雜度更容易複雜,因此本博文也在標題指明討論的是時間複雜度。通常狀況下,沒有特殊說明,複雜度就是指時間複雜度函數

時間頻度: 一個算法中的語句執行次數稱爲語句頻度或時間頻度。post

一個算法執行所消耗的時間,從理論上是不能算出來的,必須上機測試才知道。但咱們不可能也沒有必要對每一個算法都上機測試,只須要知道哪一個算法花費的時間多,哪一個算法花費的時間少就能夠了。而且一個算法花費的時間與算法中語句執行次數成正比例,哪一個算法中執行語句次數多,它話費的時間就多。測試

時間複雜度: 執行程序所需的時間。(上面提到了)

通常狀況下,算法中基本操做重複執行的次數是問題規模n的某個函數,用T(n)表示,如有某個輔助函數f(n),使得當n趨近無窮大時,T(n)/f(n)的極限值爲不等於零的常數,則稱爲f(n)是T(n)的同數量級函數。記做T(n)=O(f(n)),稱O(f(n))爲算法的漸進時間複雜度,簡稱時間複雜度。好比:

在 T(n)=4nn-2n+2 中,就有f(n)=nn,使得T(n)/f(n)的極限值爲4,那麼O(f(n)),也就是時間複雜度爲O(n*n)

大O表示法: 算法的時間複雜度一般用大O符號表述,定義爲T(n)=Of((n))【上面有提到並舉例】。

T(n) = O(f(n))稱函數T(n)以f(n)爲界或稱T(n)受限於f(n)。若是一個問題的規模是n,解決一問題的某一算法所須要的時間爲T(n)。

【注】時間複雜度和時間複雜度雖然在概念上有所區別,可是在某種狀況下,能夠認爲二者是等價的或者是約等價的。

大O階推導

推導大O階就是將算法的全部步驟轉換爲代數項,而後排除不會對問題的總體複雜度產生較大影響的較低階常數和係數。

有條理的說,推導大O階,按照下面的三個規則來推導,獲得的結果就是大O表示法:

  1. 運行時間中全部的加減法常數用常數1代替
  2. 只保留最高階項
  3. 去除最高項常數

先來看下圖,對各個時間複雜度認下臉:

comparision_computational_cmplexity

O(1)常數階

let sum = 0,
    n = 100; // 執行一次
sum = (1+n)*n/2; // 執行一次
console.log(sum); // 執行一次 
複製代碼

上面算法的運行次數的函數是f(n)=3,則有O(f(n) = 3)即O(3), 常數項用常數1表示,則最終的表示法爲O(1),咱們稱之爲常數階。

O(n)線性階

線性階主要分析循環結構的運行狀況,以下:

for(let i = 0; i < n; i++){
    // 時間複雜度O(1)的算法
    ...
}
複製代碼

上面算法循環體中的代碼執行了n次,所以時間複雜度是O(n)

O(logn)對數階

let number = 1;
while(number < n){
    number = number*2;
    // 時間複雜度O(1)的算法
    ...
}
複製代碼

上面的代碼,隨着number每次乘以2後,都會越來約接近n,當number不小於n時候就會退出循環。假設循環的次數爲x,則由2^x=n得出x=log₂n,所以獲得這個算法的時間複雜度爲O(logn)

O(n²)平方階

平凡階通常出如今嵌套的循環中,以下:

for(let i=0; i<n; i++){
    for(let j=i; j<n; j++){
        // 時間複雜度O(1)的算法
        ...
    }
}
複製代碼

上面的代碼中,內循環的中是j=i。具體的算法過程以下:

n+(n-1)+(n-2)+(n-3)+……+1
=(n+1)+[(n-1)+2]+[(n-2)+3]+[(n-3)+4]+……
=(n+1)+(n+1)+(n+1)+(n+1)+……
=(n+1)n/2
=n(n+1)/2
=n²/2+n/2
複製代碼

根據上面說的推導大O階的規則,獲得上面這段代碼的時間複雜度是O(n²)

其餘常見覆雜度

f(n)=nlogn時,時間複雜度爲O(nlogn),能夠稱爲nlogn階。

f(n)=n³時,時間複雜度爲O(n³),能夠稱爲立方階。

f(n)=2ⁿ時,時間複雜度爲O(2ⁿ),能夠稱爲指數階。

f(n)=n!時,時間複雜度爲O(n!),能夠稱爲階乘階。

f(n)=(√n時,時間複雜度爲O(√n),能夠稱爲平方根階。

時間複雜度比較

嗯,咱們再回頭看下下面的圖片:

comparision_computational_cmplexity

經過圖片直觀的體現,可以獲得經常使用的時間複雜度按照消耗時間的大小從小到大排序依次是:

O(1)<O(logn)<O(n)<O(nlogn)<O(n²)<O(n³)<O(2ⁿ)<O(n!)

參考

bigocheatsheet.com/

劉望舒 -- juejin.im/post/5bbd79…

李斌 -- zhuanlan.zhihu.com/p/32135157

後話

文章首發 -- github-算法的時間複雜度

嗯,當年上的算法課,如今丟掉的總得還,因此本身新建了一個倉庫來管理--github-js_algorithm,有興趣能夠喵一下。共勉@~@

相關文章
相關標籤/搜索