空間複雜度
時間與空間的取捨
總結通過上一節的學習,可以了解到時間複雜度和空間複雜度實際上就是時間成本與空間成本,那麼這一節主要說一下空間複雜度。
程式在執行的過程中除了需要執行各種各樣的指令,同時也會根據實際情況,開闢出一些空間,儲存一些臨時資料
,這樣做的好處是通過臨時資料可以加快訪問速度,減少開銷。
那麼什麼時候需要這些臨時資料呢?
假定存在乙個整數列,其中有且僅有2個整數是重複的,要求找出這2個整數:
看到這個題目,最容易被大眾所想到的演算法就是雙重迴圈,通過遍歷整個數列,每遍歷到乙個整數,就把它與之前所有遍歷過的整數逐一比較,判斷是否重複。
數列:[5,1,2,6,7,3,6]
第一步:遍歷第乙個整數5,前面沒有數字,所以無法回顧。
第二步:遍歷第二個整數1,回顧前面的整數5,沒有重複。
第三步:遍歷第三個整數2,回顧前面的整數5,1,沒有重複。
...第七步:遍歷第七個整數6,回顧前面的整數5,1,2,6,7,3,發現與6重複了,得到結果[6,6]。
乍一看好像這個演算法並沒有什麼問題,但是我們來看看它的時間複雜度是多少呢?
而o(n^2)是上一節講到的4種時間複雜度裡效率最低的乙個,所以剛才這種演算法並不是乙個好的演算法。
那麼如何提高演算法的效率呢?
這時,我們就需要一些臨時資料了。
還是剛才的題目,當遍歷整個數列時,我們可以將遍歷過的整數找乙個類似「字典」的資料結構給儲存起來,並將「字典」的key設為整數的值,而將value設為整數出現的次數,如果之前出現過這個整數,則value值+1,這樣在進行下一次遍歷的時候,就不需要再去回顧比較前面的整數,只需要一次遍歷,就可以得到每個整數出現重複的次數。
遍歷[5,1,2,6,7,3,6],得到:
k v
5 1
1 1
2 1
6 2
7 1
3 1
當把數列遍歷完,就可以很清晰的看到6出現了2次,那麼這種演算法的時間複雜度是多少呢?
由於只有1次遍歷行為,所以整個演算法的時間複雜度是o(n),相比較之前的o(n^2),在演算法的效率上是有質的提公升的。
而剛才所用到的「字典」,是一種特殊的資料結構,叫雜湊表
,也叫雜湊表
,這個資料結構是需要開闢一定的記憶體空間來儲存資料資訊的。
但是記憶體空間也是有限的資源,自然是用的越少越好,而描述乙個演算法的記憶體空間所用大小,就用到了乙個重要的指標:空間複雜度
。
和時間複雜度類似,空間複雜度是演算法在執行過程中臨時占用儲存空間大小的量度,它同樣使用了大o表示法。
程式占用空間大小的計算公式記作:s(n) = o(f(n))
其中n為問題的規模,f(n)為演算法所占用儲存空間的函式。
是不是又懵了?沒事,習慣成自然,用多了自然就會了,接著看。
常見的空間複雜度有以下幾種情形:
當演算法的儲存空間大小固定,和輸入規模沒有直接關係時,空間複雜度記作:o(1)
當演算法分配的空間是乙個線性的集合(或陣列),並且集合的大小和輸入規模n成正比的時候,空間複雜度記作:o(n)
當演算法分配的空間是乙個二維陣列,並且集合的長度和寬度都與輸入規模n成正比的時候,空間複雜度記作:o(n^2)
遞迴是乙個比較特殊的場景,雖然遞迴**中並沒有顯式地宣告變數或者集合,但是計算機在執行程式的時候,會專門分配一塊記憶體空間,用來儲存方法呼叫棧
,如果遞迴的深度為n,那麼空間複雜度為o(n)
方法呼叫棧包括進棧和出棧2個行為,具體會在後面的章節進行說明。
絕大多數的時候,時間複雜度更為重要一些,我們寧願多分配一些記憶體空間,也要提公升演算法的執行速度。
資料結構時間複雜度 資料結構與演算法之演算法概述
演算法,對應的英文單詞是algorithm,這是乙個很古老的概念,最早來自數學領域。我們都聽過高斯小時的故事和高斯演算法,這裡就不多說了,這是數學領域中演算法的乙個簡單示例。在數學領域裡,演算法是用於解決某一類問題的公式和思想。而我這裡所講的演算法,是電腦科學領域的演算法,它的本質是一系列程式指令,...
資料結構之演算法時間複雜度
演算法的時間複雜度定義為 在進行演算法分析時,語句總的執行次數t n 是關於問題規模n的函式,進而分析t n 隨n的變化情況並確定t n 的數量級。演算法的時間複雜度,也就是演算法的時間量度,記作 t n 0 f n 它表示隨問題規模n的增大,演算法執行時間的埔長率和 f n 的埔長率相同,稱作演算...
資料結構之演算法時間複雜度
資料結構之演算法時間複雜度 演算法的時間複雜度定義為 在進行演算法分析時,語句總的執行次數t n 是關於問題規模n的函式,進而分析t n 隨n的變化情況並確定t n 的數量級。演算法的時間複雜度,也就是演算法的時間量度,記作 t n 0 f n 它表示隨問題規模n的增大,演算法執行時間的埔長率和 f...