遊戲中的算法:算法的時間複雜度

作爲學渣出生的程序員,在面試的時候被面試官問道:什麼是時間的複雜度?
我:時間複雜度就是一個方法運行的大概時間!(雖然不懂,但是這個還是知道的)
面試官:它是怎麼計算的?
我:看過,但是沒看懂(汗汗–!)
面試官:這都看不懂?

我還能說啥?在面試之前,專門找過相關的文章學習,但是,真的沒看懂!!!
入職後,打算認真的研究以下算法的複雜度,也記錄一下的成長曆程!!!

同一個問題,有不同的解決方法,有的方法快,有的方法慢。算法與此相同,而一個算法質量將影響到算法乃至整個程序的效率。

一個算法的好壞主要是從時間複雜度空間複雜度來衡量的。
時間複雜度:
算法執行所消耗的時間,理論上計算不出來的,但我們知道哪個個算法中語句執行次數越多,它花費時間也就越多。一個算法中的語句執行次稱爲語句頻度或時間頻度,記爲T(n)。而算法的時間複雜度也就指執行算法所需要的計算工作量。
T(n) 即爲一個函數,n是一個自變量,也就以n爲自變量組成的函數
n稱爲問題的規模,當n不斷變化時,T(n)也不會變化。

時間複雜度通常用大寫字母O來表示,O表示法有以下規則:
1.忽略常數項
表達式:O© = O(1) 例:O(10) = O(1)
例如:T(n)= n+50 表示一個計算運行時間的算法,當n=1024時,此表達式的常數項 對運行時間的影響僅爲4.8% ( 50/n)
2.忽略常數因子
表達式:O(cT) = cO(T) = O(T) 例:O(10n) = O(n) (c爲常數)
例如:T(n)=n2(1) 和 T(n) = 10n(2) 兩個運行時間的算法,當(1)中的n大於10 時,(1)就會大於(2)。
3.忽略低階相的因子
表達式:O(T1) + O(T2) = max(O(T1),O(T2)) 例:O(n)+O((n2) = O(n2)
例如:T(n) =n^2+n 是一個運行時間的算法,當n爲1024時,表達式中的低階項因子的 值已經佔不到運行時間的0.1%。

爲什麼?看這個例子:
有時間算法: T(n)=3n2+10n+10
則時間複雜度爲:
O(T(n)) = O(3n2+10n+10) = O(3n2) = O(n2)

當n = 10 時:
3n2/T(n) = 73.2%
10n/T(n) = 24.4%
10/T(n) = 2.4%

當 n=100時:
3n2/T(n) =96.7%
10n/T(n) = 3.2%
10/T(n) = <0.1%
可以看到n2佔據了幾乎整個運行時間。

按數量級遞增,常見的時間複雜度:
常數階:O(1) 從一個數據集中獲取第一個元素
對數階:O(log2n) 將一個數據集分成兩半,然後將分開的每一半再分成兩半,一次類推(以2爲底n的對數)
對數:如果x^2=n ,那麼2就爲以x爲底n的對數。也就對求冪的逆運算
線性階:O(n) 遍歷一個數據集
線性對數階:O(nlog2n) 將一個數據集分成兩半,然後將分開的沒一半再分成兩半,依次類推,再此過程中同時遍歷每一半數據
平方階:O(n^2) 遍歷一個數據集中每個元素的同時遍歷另一個數量級相同的數據集
指數階:O(2^n) 爲一個數據集生成其可能的所有子集
階乘階:O(n!) 爲一個數據集生成其可能的所有排列組合
隨着問題規模n的不斷增大,上述時間複雜度不斷增大,算法的執行效率越低。
如圖:
在這裏插入圖片描述
時間複雜度怎麼分析的呢?
算法所耗的時間=算法中每條語句的執行時間之和
每條語句的執行時間=語句執行的次數(頻度)*語句執行一次所需的時間。
每條語句執行的時間取決與機器的指令性能,速度以及編譯所產生的代碼質量等等因素,所以通常假設每條語句執行一次所需要的時間爲1。
最終一個算法的時間耗費爲:
時間 = 所有語句的頻度之和

例如:求冒泡排序的時間複雜度

function BubbleSort(list)
	for i = 1,table.getn(list) - 1 do		            
		for j = 1,table.getn(list) - 1 - i do		   	 
			if list[j] > list[j+1] then							
				list[j],list[j+1] = list[j+1],list[j]
			end
		end
	end
end

在冒泡排序算法中,總共有兩個for循環,分別用1和 2 來標識,
假設,我們傳入的待排數組的長度爲n,那麼第一層循環需要執行n-1次(其實需要執行n-1+1次,因爲for語句和額外比較一次來確定是否需要繼續循環)。
第二層循環執行爲:
i=1,n’ = n-1,
i=2, n‘ = n-2

i = n-1-1,n’ = n-(n-1-1)
明顯點,就是帶入一個數,假設n = 5
那就是
5
4
3
2
1
那麼明顯就是等差序列了,等差序列求和公式
(首項+末項)*項數/2 = (n+1)n/2 = (n(n+1))/2
根據以上:
T(n) = (n2+n)/2
然後根據O表示法:
1.忽略常數項
2.忽略常數係數
3.忽略最低階
那麼O(T(n)) = O(n2)

在例如:選擇排序法:

function SelectionSort(t)
	local pos = 1;
	for i=1,#t do
		pos =i;
		for j=1+i,table.getn(t) do
			if t[j] < t[pos] then
				pos = j;
			end
		end
		t[pos],t[i] = t[i],t[pos]
	end
end

首層for循環 需要執行n次,需要執行2,3,4,5,6…n也是等差序列求和,所以最壞的時間複雜度爲O(n2)

空間複雜度:
空間複雜度是指算法在計算機內執行時所需儲存空間的度量。計算S(n) = O(f(n))
算法執行期間所需要的存儲空間包含三個部分:
1.算法程序所佔的空間
2.輸入的初始數據所佔的存儲空間
3.算法執行過程中所需要的額外空間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章