前端 算法的時間復雜度和空間復雜度


 

 

算法的評估

對於一個問題,經常有多種不同的求解算法,這時候我們就需要一個對算法進行評估的標准,找出最優的方案,評估一個算法有以下幾個維度:

  • 正確性:能正確的實現功能,滿足問題的需求。
  • 易讀性:通常,寫出一個利與人類閱讀的代碼和利於機器閱讀的代碼一樣重要
  • 健壯性:對於預料之外的輸入,也能做出合適的處理。
  • 時空性:算法的時間性能(算法的計算量)和空間性能(算法需要的存儲量)、

時間復雜度

時間復雜度的計算方法

時間復雜度:在給定輸入(問題規模)下,算法的計算量。

所以說,求一個算法的時間復雜度,就是求這個算法在給定問題規模下的計算量,那么問題來了:如何求算法的計算量?

算法計算量的求法規則如下:

  • 1、在算法中選擇幾種“基本操作”,例如:賦值語句、數學運算語句等等。
  • 2、給定輸入下,計算算法執行了多少次“基本操作”。
  • 3、“基本操作”的次數即可作為計算量。
實例與大O表示法

我們以一個例子來說明,求如下表達式的值:

// 階乘的和
1! + 2! + 3! + ... + n!

我們可以寫出如下程序(js代碼):

function factorial (n) { var s = 0, temp = 1 for (var i = 1; i <= n; i++) { temp = 1 for (var j = 1; j <= i; j++) { temp *= j } s += temp } return s } 

我們根據之前總結的算法計算量的求法規則可知,求解一個算法的計算量分為三個步驟,第一步:確定基本操作,對於上面的代碼我們所挑選的基本操作如下:

  • 第一部分賦值語句:
    var s = 0 temp = 1 

當我們的輸入規模即 n 變化時,這兩條語句的執行次數沒有變,始終是 2 次。

  • 第二部分賦值語句:

    for (var i = 1; i <= n; i++) { temp = 1 ... } 

    第一層循環里的 temp = 1,該語句的執行次數等於輸入規模 n

  • 乘法計算語句:

for (var j = 1; j <= i; j++) { temp *= j } 

第二層循環里的 temp *= j,該語句的執行次數,當 n = 1 時執行 1 次,當 n = 2 時執行 1 + 2 次,當 n = 3 時執行 1 + 2 + 3 次,所以該語句的執行次數與輸入規模 n 的關系是 1 + 2 + 3 + ... + n = n(n + 1) / 2

  • 加法計算語句:
    for (var i = 1; i <= n; i++) { ... s += temp } 
    第一層循環里的加法賦值語句,該語句的執行次數等於輸入規模 n

綜上所述,根據我們選擇的“基本操作”,可以計算出該算法的基本操作次數與輸入規模 n 的關系如下:

T(n) = 2 + n + n(n + 1) / 2 + n = 1/2n^2 + 3/2n + 2 

當 n 足夠大時,n^2 起支配作用,使用 O(n^2) 表示 T(n) 的近似值,這種表示法成為 大 O 表示法

常見的時間復雜度階數
  • 常熟階 O(1):即算法的計算量不隨着輸入規模的變化而變化。
  • 線性階 O(n)
  • 多項式階 O(n^c):常見的多項式階如 O(n^2)、O(n^3)
  • 指數階 O(C^n):常見的指數階如 O(2^n)

一般我們認為一個算法的時間復雜度為指數階的時候,該算法是實際不可運算的,大家可以想象一下,如果一個算法的時間復雜度為 O(2^n) 當 n = 1000 時,這個數值是何等恐怖。更何況我們的輸入規模 n 很可能遠大於 1000。

另外我們認為時間復雜度為 O(n)O(log2N)O(n^2) 是高效的算法。對於合理大的 nO(n^3) 也是可以接受的。

空間復雜度

空間復雜度的計算方法

空間復雜度:給定輸入(問題規模)下,算法運行時所占用的臨時存儲空間。

一個算法執行期間所占用的存儲量分為三部分:

  • 算法本身的代碼所占用的空間
  • 輸入數據所占用的空間
  • 輔助變量所占用的空間

由於實現不同算法所需的代碼不會有數量級的差別,所以算法本身代碼所占用的空間我們可以不考慮

輸入的數據所占用的空間是由問題決定的,與算法無關,所以我們也不需要考慮

我們需要考慮的只有一個:程序執行期間,輔助變量所占用的空間。

計算方法類似於計算算法的時間復雜度,空間復雜度我們用 S(n) 來表示,它同樣是輸入數據規模 n 的函數,用大 O 表示法記為:

S(n) = O(g(n))

其中 g(n) 是一個關於 n 的函數,如:g(n) = ng(n) = n^2g(n) = log2N 等等。

實例

假設我們有一個數組,該數組有100個元素,寫一個轉置該數組的算法:

function reverse (arr) { for (var i = 0; i <= arr.length / 2 - 1; i++) { var temp = arr[i] arr[i] = arr[arr.length - i - 1] arr[arr.length - i - 1] = temp } } 

上面的算法中,我們采用中間變量 temp 對數組的值進行逐個對應的首尾交換,最終達到轉置的目的,我們可以看到,輔助變量只有一個即 temp,該變量存儲一個數字類型的值,temp 所占用的內存不會隨輸入數組規模的增大而增大,所以上面算法的控件復雜度為 O(1),是常數階,即上面算法的空間復雜度 S(n) = O(1)

 

from: http://blog.poetries.top/js-knowledge-note/#/note/algorithm/time-space


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM