演算法的時間複雜的分析 推導大O

2022-02-18 08:43:55 字數 3834 閱讀 8235

在進行演算法分析時,語句總的執行次數t(n)是關於問題規模n的函式,進而分析t(n)隨n的變化情況並確定t(n)的數量級。演算法的時間複雜度,

也就是演算法的時間量度,

記作t(n)=o(f(n))。它表示隨問題規模n的增大,演算法執行時間的增長率和f(n)的增長率相同,稱作演算法的漸進演算法時間複雜度,簡稱為時間複雜度。

其中f(n)是問題規模n的某個函式。

一般用大寫o()來表示演算法的時間複雜度寫法,通常叫做大o記法。

一般情況下,隨著n的增大,t(n)增長最慢的演算法為最優演算法。

o(1):常數階

o(n):線性階

o(n2):平方階

o(logn):對數階

用常數1取代執行時間中的所有加法常數

在修改後的執行函式中,只保留最高端項

如果最高端項存在且不是1,則去除與這個項相乘的常數

3.1常數階:

int sum = 0 ; n = 100;        /*

執行一次

*/sum = (1+n)*n/2; /*

執行一次

*/printf("%d

",sum); /*

執行一次

*/

這個演算法的執行次數f(n) = 3,根據推導大o階的方法,第一步是將3改為1,在保留最高端項是,它沒有最高端項,因此這個演算法的時間複雜度為o(1);

另外我們將sum  = (1+n)*n/2;執行10次

int sum = 0 ; n = 100;        /*

執行一次

*/sum = (1+n)*n/2; /*

執行第1次

*/sum = (1+n)*n/2; /*

執行第2次

*/sum = (1+n)*n/2; /*

執行第3次

*/sum = (1+n)*n/2; /*

執行第4次

*/sum = (1+n)*n/2; /*

執行第5次

*/sum = (1+n)*n/2; /*

執行第6次

*/sum = (1+n)*n/2; /*

執行第7次

*/sum = (1+n)*n/2; /*

執行第8次

*/sum = (1+n)*n/2; /*

執行第9次

*/sum = (1+n)*n/2; /*

執行第10次

*/printf("%d

",sum); /*

執行一次

*/

上面的兩段**中,其實無論n有多少個,本質是是3次和12次的執行差異。這種與問題的大小無關,執行時間恆定的演算法,成為具有o(1)的時間複雜度,又叫做常數階。

注意:不管這個常數是多少,3或12,都不能寫成o(3)、o(12),而都要寫成o(1),這一點要特別注意。

此外,對於分支結構而言,無論真假執行的次數都是恆定不變的,不會隨著n的變大而發生變化,所以單純的分支結構(不在迴圈結構中),其時間複雜度也是o(1)。

3.2線性階

線性階的迴圈結構會複雜一些,要確定某個演算法的階次,需要確定特定語句或某個語句集執行的次數。因此要分析演算法的複雜度,關鍵是要分析迴圈結構的運**況。

此時得到時間複雜的為o(n)

int

i;for(i = 0 ; i < n ; i++)

3.3平方階

int

i;for(i = 0 ; i < n ; i++)

}

上面的程式中,對於對於內層迴圈,它的時間複雜度為o(n),但是它是包含在外層迴圈中,再迴圈n次,因此這段**的時間複雜度為o(n2)。

int

i;for(i = 0 ; i < n ; i++)

}

但是,如果內層迴圈改成了m次,時間複雜度就為o(n*m)

再來看一段稍微複雜一點的程式

int

i;for(i = 0 ; i < n ; i++)

}

這段**的時間複雜度又是多少呢?

分析一下:外層迴圈執行n次,每執行一次,內層的迴圈次數就比上一次減一

注意:上面的內層迴圈j = i ;而不是0

因為i = 0時,內層迴圈執行了n次,當i=1時,執行了n-1次……當i=n-1時,執行了1次,所以總的執行次數為:

n+(n-1)+(n-1)+...+1 =n(n+1)/2  = n2/2 + n

/2根據大o推導方法,保留最高端項,n2/2 ,然後去掉這個項相乘的常數,1/2

因此,這段**的時間複雜度為o(n2)

3.4對數階

int count = 1;

while(count < n)

因為每次count*2後,距離結束迴圈更近了。也就是說有多少個2 相乘後大於n,退出迴圈。

數學公式:2x = n    -->     x = log2

n因此這個迴圈的時間複雜度為o(logn)

3.5呼叫函式時的時間複雜度計算方法:

int

i,j;

void function(int

count)

for(i = 0 ; i < n ; i++)

這個時候就可以直接把函式體放到迴圈內部,然後進行判斷。

函式的時間複雜度是o(1),因此整體的時間複雜度為o(n)。

假如function是這樣的:

void function(int

count)

}

和第乙個的不同之處在於函式體的內容改變了,變成了線性階,所以可以把整體看成平方階,因此最終的時間複雜度為o(n2)

最後看乙個比較複雜的

n++;                                      /*

執行次數為1

*/function(n);

/*執行次數為n

*/int

i,j;

for(i = 0 ; i < n ; i++)

for(i = 0 ; i < n ; i++)

}

它的執行次數f(n) = 1 + n + n2 + n(n+1)/2 + 3/2n2+3/2 n+1,

根據推導大o階的方法,最終它的時間複雜度為:o(n2)

執行次數函式

術語描述

12o(1)

常數階2n+3

o(n)

線性階3n2+2n+1

o(n2)

平方階5log2

n+20

o(log2

n)對數階

2n+3nlog2

n+19

o(nlogn)

nlog2

n階6n3+2n2+3n+4

o(n3)

立方階2n

o(2n)

指數階時間複雜度所耗費的時間是:

o(1) < o(logn) < o(n) < o(nlogn) < o(n2) < o(n3) n) < o(n!) n)

參考文獻:《大話資料結構》

時間複雜度 大O演算法

演算法的執行效率,就是演算法 的執行時間。我們需要能夠用肉眼就看出一段 的執行時間。int cal int n return sum 2,3行都執行了1個unit time的執行時間,4,5行都執行了n遍,所以是2n unit time的執行時間,所以一共是 2n 2 unit time。所有的 的...

時間複雜度分析 大O記法

就是看乙個程式執行消耗的時間,這個最簡單的分析方法但是有很大的缺點 用這種方式去測試需要等待程式執行完畢,浪費了很多時間在等待程式執行上 對於不同的硬體條件,程式執行的速度都是不一樣的,這樣的結果就沒有說服力 程式設計師主要關注的是 使用什麼演算法實現 乙個問題的規模 設t n 為問題規模n的函式,...

演算法的時間複雜度與大O記法

演算法的時間複雜度 演算法的時間複雜度是乙個關於問題規模n的函式,而且這個函式描述了cpu執行演算法所需要的時間。大o記法 描述時間複雜度優劣的一種記法。2 推導大o階的方法 假設演算法的時間複雜度為t n 1.只保留最高端項 2.將最高端項的常數改為1 第一步 計算語句執行次數t n void m...