《大话数据结构》第2章 算法基础 2.9 算法的时间复杂度
?
2.9.1?算法時間復雜度定義
??????? 在進行算法分析時,語句總的執(zhí)行次數(shù)T(n)是關于問題規(guī)模n的函數(shù),進而分析T(n)隨n的變化情況并確定T(n)的數(shù)量級。算法的時間復雜度,也就是算法的時間量度,記作:T(n) = O(f(n))。它表示隨問題規(guī)模n的增大,算法執(zhí)行時間的增長率和f(n)的增長率相同,稱作算法的漸近時間復雜度,簡稱為時間復雜度。其中f(n)是問題規(guī)模n的某個函數(shù)。
??????? 這樣用大寫O()來體現(xiàn)算法時間復雜度的記法,我們稱之為大O記法。
??????? 一般情況下,隨著n的增大,T(n)增長最慢的算法為最優(yōu)算法。
??????? 顯然,由此算法時間復雜度的定義可知,我們的三個求和算法的時間復雜度分別為O(n),O(1),O(n2)。我們分別給它們?nèi)×朔枪俜降拿Q,O(1)叫常數(shù)階,O(n)叫線性階,O(n2)叫平方階,當然,還有其他的一些階,我們之后會介紹。
2.9.2?推導大O階方法
??????? 那么如何分析一個算法的時間復雜度呢?即如何推導大O階呢?我們給出了下面的推導方法,基本上,這也就是總結前面我們舉的例子
推導大O階1.用常數(shù)1取代運行時間中的所有加法常數(shù)。2.在修改后的運行次數(shù)函數(shù)中,只保留最高階項。
3.如果最高階項存在且不是1,則去除與這個項相乘的常數(shù)。
得到的結果就是大O階。
??????? 哈,仿佛是得到了游戲攻略一樣,我們好像已經(jīng)得到了一個推導算法時間復雜度的萬能公式。可事實上,分析一個算法的時間復雜度,沒有這么簡單,我們還需要多看幾個例子。
2.9.3?常數(shù)階
??????? 首先順序結構的時間復雜度。下面這個算法,也就是剛才的第二種算法,為什么時間復雜度不是O(3),而是O(1)。
?
int?sum?=?0,n?=?100;??/*執(zhí)行一次*/sum?=?(1+n)*n/2;???/*執(zhí)行一次*/
printf("%d",?sum);??/*執(zhí)行一次*/
??????? 這個算法的運行次數(shù)函數(shù)是f(n)=3。根據(jù)我們推導大O階的方法,第一步就是把常數(shù)項3改為1。在保留最高階項時發(fā)現(xiàn),它根本沒有最高階項,所以這個算法的時間復雜度為O(1)。
??????? 另外,我們試想一下,如果這個算法當中的語句sum=(1+n)*n/2有10句,即:
?
int?sum?=?0,?n?=?100;?/*執(zhí)行一次*/sum?=?(1+n)*n/2;???/*執(zhí)行第1次*/
sum?=?(1+n)*n/2;???/*執(zhí)行第2次*/
sum?=?(1+n)*n/2;???/*執(zhí)行第3次*/
sum?=?(1+n)*n/2;???/*執(zhí)行第4次*/
sum?=?(1+n)*n/2;???/*執(zhí)行第5次*/
sum?=?(1+n)*n/2;???/*執(zhí)行第6次*/
sum?=?(1+n)*n/2;???/*執(zhí)行第7次*/
sum?=?(1+n)*n/2;???/*執(zhí)行第8次*/
sum?=?(1+n)*n/2;???/*執(zhí)行第9次*/
sum?=?(1+n)*n/2;???/*執(zhí)行第10次*/
printf("%d",sum);??/*執(zhí)行一次*/?
??????? 事實上無論n為多少,上面的兩段代碼就是3次和12次執(zhí)行的差異,這種與問題的大小無關(n的多少),執(zhí)行時間恒定的算法,我們稱之為具有O(1)的時間復雜度,又叫常數(shù)階。
??????? 注意,不管這個常數(shù)是多少,我們都記作O(1),而不能是O(3)、O(12)等其他任何數(shù)字。這是初學者常常犯的錯誤。
??????? 對于分支結構而言,無論是真,還是假,執(zhí)行的次數(shù)都是恒定的,不會隨著n的變大而發(fā)生變化,所以單純的分支結構(不包含在循環(huán)結構中),其時間復雜度也是O(1)。
2.9.4?線性階
??????? 循環(huán)結構就會復雜很多。要確定某個算法的階次,我們常常需要確定某個特定語句或某個語句集運行的次數(shù)。因此,我們要分析算法的復雜度,關鍵就是要分析循環(huán)結構的運行情況。
??????? 下面這段代碼,它的循環(huán)的時間復雜度為O(n)。因為循環(huán)體中的代碼須要執(zhí)行n次。
for(i?=?0;?i?<?n;?i++)
{
???/*時間復雜度為O(1)的程序步驟序列*/
}
2.9.5?對數(shù)階
??????? 那么下面的這段代碼,時間復雜度又是多少呢?
int?count?=?1;
while?(count?<?n)
{
???count?=?count?*?2;
???/*時間復雜度為O(1)的程序步驟序列*/
}
??????? 由于每次count乘以2之后,就距離n更近了一分。也就是說,有多少個2相乘后大于n,則會退出循環(huán)。由2x=n得到x=log2n。所以這個循環(huán)的時間復雜度為O(logn)。
2.9.6?平方階
??????? 下面的例子是一個循環(huán)嵌套,它的內(nèi)循環(huán)剛才我們已經(jīng)分析過,時間復雜度為O(n)。
?
int?i,j;for(i?=?0;?i?<?n;?i++)
{
???for?(j?=?0;?j?<?n;j++)???????????????????????
???{??????????????????????????????????????
???????/*時間復雜度為O(1)的程序步驟序列*/
???}??????????????????????????????????????
}
??????? 而對于外層的循環(huán),不過是內(nèi)部這個時間復雜度為O(n)的語句,再循環(huán)n次。所以這段代碼的時間復雜度為O(n2)。
??????? 如果外循環(huán)的循環(huán)次數(shù)改為了m,時間復雜度就變?yōu)镺(m×n)。
for(i?=?0;?i?<?m;?i++)
{
???for?(j?=?0;?j?<?n;?j++)????????????????
???{??????????????????????????????????????
???????/*時間復雜度為O(1)的程序步驟序列*/
???}??????????????????????????????????????
}
??????? 所以我們可以總結得出,循環(huán)的時間復雜度等于循環(huán)體的復雜度乘以該循環(huán)運行的次數(shù)。
??????? 那么下面這個循環(huán)嵌套,它的時間復雜度是多少呢?
int?i,j;
for(i?=?0;?i?<?n;?i++)
{
????for?(j?=?i;?j?<?n;?j++)??/*注意int?j?=?i而不是0*/
????{??????????????????????????????????????
??????????/*時間復雜度為O(1)的程序步驟序列*/
????}??????????????????????????????????????
}
??????????????由于當i = 0時,內(nèi)循環(huán)執(zhí)行了n次,當i = 1時,執(zhí)行了n-1次,……當i = n-1時,內(nèi)循環(huán)執(zhí)行了1次。所以總的執(zhí)行次數(shù)為
?
??????? 用我們推導大O階的方法,第一條,沒有加法常數(shù)不予考慮;第二條,只保留最高階項,因此保留n2/2;第三條,去除這個項相乘的常數(shù),也就是去除1/2,最終這段代碼的時間復雜度為O(n2)。
??????? 從這個例子,我們也可以得到一個經(jīng)驗,其實理解大O推導不算難,難的是對數(shù)列的一些相關運算,這更多的是考察你的數(shù)學知識和能力,所以想考研的朋友,要想在求算法時間復雜度這里不失分,可能需要強化你的數(shù)學,特別是數(shù)列方面的知識和解題能力。
??????? 我們繼續(xù)看例子,對于方法調(diào)用的時間復雜度又如何分析。
?
int?i,j;for(i?=?0;?i?<?n;?i++)
{
???function(i);
}
?
????????????? 上面這段代碼調(diào)用一個函數(shù)function。
{
???print(count);
}
???????函數(shù)體是打印這個參數(shù)。其實這很好理解,function函數(shù)的時間復雜度是O(1)。所以整體的時間復雜度為O(n)。
?????? 假如function是下面這樣的:
{
???int?j;
???for?(j?=?count;?j?<?n;j++)???????????????????????
???{??????????????????????????????????????
??????/*時間復雜度為O(1)的程序步驟序列*/
???}????
}?
??????? 事實上,這和剛才舉的例子是一樣的,只不過把嵌套內(nèi)循環(huán)放到了函數(shù)中,所以最終的時間復雜度為O(n2)。
??????? 下面這段相對復雜的語句:
function(n);?????/*執(zhí)行次數(shù)為n*/
int?i,j;?????
for(i?=?0;?i?<?n;?i++)??/*執(zhí)行次數(shù)為n2*/
{
???function?(i);
}
for(i?=?0;?i?<?n;?i++)??/*執(zhí)行次數(shù)為n(n?+?1)/2*/
{
???for?(j?=?i;j?<?n;?j++)???????????????????????
???{??????????????????????????????????????
????????/*時間復雜度為O(1)的程序步驟序列*/
???}??????????????????????????????????????
}
?
???????? 它的執(zhí)行次數(shù) ,根據(jù)推導大O階的方法,最終這段代碼的時間復雜度也是O(n2)。
出處:http://www.cnblogs.com/cj723/archive/2011/03/05/1971640.html
總結
以上是生活随笔為你收集整理的《大话数据结构》第2章 算法基础 2.9 算法的时间复杂度的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《大话数据结构》第2章 算法基础 2.8
- 下一篇: 《大话数据结构》第3章 线性表 3.8.