時間復雜度,換句話說,就是它們運行得有多快。但有些時候,我們還得以另一種名為空間復雜度的度量方式,去估計它們會消耗多少內存。
當內存有限時,空間復雜度便會成為選擇算法的一個重要的參考因素。比如說,在給小內存的小型設備寫程序時,或是處理一些會迅速占滿大內存的大數據時都會考慮空間復雜度。
描述空間復雜度的大O記法
計算機科學家還是用描述時間復雜度的大O記法來描述空間復雜度。 用大O來描述一個算法需要多少空間:當所處理的數據有N個元素時,該算法還需額外消耗多少元素大小的內存空間。
function makeUpperCase(array){//makeUpperCase函數接收一個數組作為參數array。 var newArray=[];//然后它創建了一個全新的數組,名為newArray for(var i=0; i < array.length; i++){ newArray[i]=array[i].toUpperCase();//並將原數組array里的字符串的大寫形式填進去。 } return newArray; }
分析該函數的話,你會發現它接收一個N元素的數組,就會產生另一個新的N元素數組。因此,我們會說這個makeUpper-Case函數的空間效率是O(N)。
我們再寫一個更高效利用內存的makeUpperCase。
function makeUpperCase(array){ for(var i=0; i < array.length; i++){ array[i]=array[i].toUpperCase(); } return array; }
因為該函數並不消耗額外的內存空間,所以我們把它的空間復雜度描述為O(1)。記住,時間復雜度的O(1)意味着一個算法無論處理多少數據,其速度恆定。相似地,空間復雜度的O(1)則意味着一個算法無論處理多少數據,其消耗的內存恆定。
值得一再強調的是,空間復雜度是根據額外需要的內存空間(也叫輔助空間)來算的,也就是說原本的數據不納入計算。盡管在第二個版本里我們有array這一入參,占用了N個元素的空間,但除此之外它並沒有消耗額外的內存,所以它是O(1)。(有些參考書在計算空間復雜度時是連原始輸入也一起算的,那沒問題。但此處我們不計算它,當你在其他地方看到某一算法的空間復雜度的描述時,最好留意一下它是否計算原始輸入。)
我們比較一下makeUpperCase兩個版本的時間復雜度和空間復雜度。
因為N項數據要花N步去處理,所以兩個版本的時間復雜度都是O(N)。然而在空間復雜度方面,第二個版本只有O(1),與第一個版本的O(N)相比,它對內存的使用效率更高。
因此選擇第二個版本更為合理。
參考:數據結構與算法圖解.14