算法筆記 —— 復(fù)雜度

算法的效率

算法的效率主要由以下兩個(gè)復(fù)雜度來(lái)評(píng)估:

  • 時(shí)間復(fù)雜度:評(píng)估執(zhí)行程序所需的時(shí)間酬屉。可以估算出程序?qū)μ幚砥鞯氖褂贸潭取?/p>

  • 空間復(fù)雜度:評(píng)估執(zhí)行程序所需的存儲(chǔ)空間蹭沛∨沤兀可以估算出程序?qū)τ?jì)算機(jī)內(nèi)存的使用程度娱节。

設(shè)計(jì)算法時(shí)挠蛉,一般是要先考慮系統(tǒng)環(huán)境,然后權(quán)衡時(shí)間復(fù)雜度和空間復(fù)雜度肄满,選取一個(gè)平衡點(diǎn)谴古。不過(guò),時(shí)間復(fù)雜度要比空間復(fù)雜度更容易產(chǎn)生問(wèn)題稠歉,因此算法研究的主要也是時(shí)間復(fù)雜度掰担,不特別說(shuō)明的情況下,復(fù)雜度就是指時(shí)間復(fù)雜度怒炸。


時(shí)間復(fù)雜度

時(shí)間頻度

一個(gè)算法執(zhí)行所耗費(fèi)的時(shí)間带饱,從理論上是不能算出來(lái)的,必須上機(jī)運(yùn)行測(cè)試才能知道阅羹。但我們不可能也沒(méi)有必要對(duì)每個(gè)算法都上機(jī)測(cè)試勺疼,只需知道哪個(gè)算法花費(fèi)的時(shí)間多,哪個(gè)算法花費(fèi)的時(shí)間少就可以了捏鱼。

一個(gè)算法花費(fèi)的時(shí)間與算法中語(yǔ)句的執(zhí)行次數(shù)成正比例执庐,哪個(gè)算法中語(yǔ)句執(zhí)行次數(shù)多,它花費(fèi)時(shí)間就多导梆。一個(gè)算法中的語(yǔ)句執(zhí)行次數(shù)稱為語(yǔ)句頻度或時(shí)間頻度轨淌。記為T(mén)(n)。

時(shí)間復(fù)雜度

前面提到的時(shí)間頻度T(n)中看尼,n稱為問(wèn)題的規(guī)模递鹉,當(dāng)n不斷變化時(shí),時(shí)間頻度T(n)也會(huì)不斷變化藏斩。

但有時(shí)我們想知道它變化時(shí)呈現(xiàn)什么規(guī)律躏结,為此我們引入時(shí)間復(fù)雜度的概念。一般情況下灾茁,算法中基本操作重復(fù)執(zhí)行的次數(shù)是問(wèn)題規(guī)模n的某個(gè)函數(shù)窜觉,用T(n)表示谷炸,若有某個(gè)輔助函數(shù)f(n),使得當(dāng)n趨近于無(wú)窮大時(shí)禀挫,T(n)/f(n)的極限值為不等于零的常數(shù)旬陡,則稱f(n)是T(n)的同數(shù)量級(jí)函數(shù),記作

T(n) = O(f(n))

它稱為算法的漸進(jìn)時(shí)間復(fù)雜度语婴,簡(jiǎn)稱時(shí)間復(fù)雜度描孟。


大O表示法

像前面用O( )來(lái)體現(xiàn)算法時(shí)間復(fù)雜度的記法,我們稱之為大O表示法砰左。

算法復(fù)雜度可以從最理想情況匿醒、平均情況和最壞情況三個(gè)角度來(lái)評(píng)估,由于平均情況大多和最壞情況持平缠导,而且評(píng)估最壞情況也可以避免后顧之憂廉羔,因此一般情況下,我們?cè)O(shè)計(jì)算法時(shí)都要直接估算最壞情況的復(fù)雜度僻造。

大O表示法O(f(n)中的f(n)的值可以為1憋他、n、logn髓削、n2等竹挡,因此我們可以將O(1)、O(n)立膛、O(logn)揪罕、O(n2)分別可以稱為常數(shù)階、線性階宝泵、對(duì)數(shù)階和平方階好啰,那么如何推導(dǎo)出f(n)的值呢?我們接著來(lái)看推導(dǎo)大O階的方法鲁猩。

推導(dǎo)大O階

推導(dǎo)大O階坎怪,我們可以按照如下的規(guī)則來(lái)進(jìn)行推導(dǎo),得到的結(jié)果就是大O表示法:

  • 1.用常數(shù)1來(lái)取代運(yùn)行時(shí)間中所有加法常數(shù)廓握。
  • 2.修改后的運(yùn)行次數(shù)函數(shù)中搅窿,只保留最高階項(xiàng)
  • 3.如果最高階項(xiàng)存在且不是1,則去除與這個(gè)項(xiàng)相乘的常數(shù)隙券。

1. 常數(shù)階 O(1)

int sum = 0,n = 100; //執(zhí)行一次  
sum = (1+n)*n/2; //執(zhí)行一次  
System.out.println (sum); //執(zhí)行一次 

上面算法的運(yùn)行的次數(shù)的函數(shù)為f(n)=3男应,根據(jù)推導(dǎo)大O階的規(guī)則1,我們需要將常數(shù)3改為1娱仔,則這個(gè)算法的時(shí)間復(fù)雜度為O(1)沐飘。如果sum = (1+n)*n/2這條語(yǔ)句再執(zhí)行10遍,因?yàn)檫@與問(wèn)題大小n的值并沒(méi)有關(guān)系,所以這個(gè)算法的時(shí)間復(fù)雜度仍舊是O(1)耐朴,我們可以稱之為常數(shù)階借卧。

只要算法中不存在循環(huán)語(yǔ)句、遞歸語(yǔ)句筛峭,即使有成千上萬(wàn)行的代碼铐刘,其時(shí)間復(fù)雜度也是O(1)。

2. 線性階 O(n)

線性階主要要分析循環(huán)結(jié)構(gòu)的運(yùn)行情況影晓,如下所示镰吵。

for(int i=0;i<n;i++){
//時(shí)間復(fù)雜度為O(1)的算法
...
}

上面算法循環(huán)體中的代碼執(zhí)行了n次,因此時(shí)間復(fù)雜度為O(n)挂签。

3. 對(duì)數(shù)階 O(logn)

int number=1;
while(number<n){
number=number*2;
//時(shí)間復(fù)雜度為O(1)的算法
...
}

可以看出疤祭,隨著number每次乘以2后,都會(huì)越來(lái)越接近n饵婆,當(dāng)number不小于n時(shí)就會(huì)退出循環(huán)勺馆。假設(shè)循環(huán)的次數(shù)為X,則由2^x=n得出x=log?n啦辐,因此得出這個(gè)算法的時(shí)間復(fù)雜度為O(logn)谓传。

3. 平方階 O(n2)

for(int i=0;i<n;i++){   
    for(int j=0;j<n;i++){
        //復(fù)雜度為O(1)的算法
        ... 
    }
}

內(nèi)層循環(huán)的時(shí)間復(fù)雜度在講到線性階時(shí)就已經(jīng)得知是O(n)蜈项,現(xiàn)在經(jīng)過(guò)外層循環(huán)n次芹关,那么這段算法的時(shí)間復(fù)雜度則為O(n2)。
接下來(lái)我們來(lái)算一下下面算法的時(shí)間復(fù)雜度:

for(int i=0;i<n;i++){   
    for(int j=i;j<n;i++){
        //復(fù)雜度為O(1)的算法
        ... 
    }
}

當(dāng)i=0時(shí)紧卒,內(nèi)循環(huán)執(zhí)行了n次侥衬;i=1時(shí)內(nèi)循環(huán)執(zhí)行了n-1次,當(dāng)i=n-1時(shí)執(zhí)行了1次跑芳,我們可以推算出總的執(zhí)行次數(shù)為:

n+(n-1)+(n-2)+(n-3)+……+1 
=(n+1)+[(n-1)+2]+[(n-2)+3]+[(n-3)+4]+…… +[n-(n-1)+n] - (1+2+...+n)
=n(n+1)-n(1+n)/2
=n(n+1)/2 
=n2/2+n/2

根據(jù)此前講過(guò)的推導(dǎo)大O階的規(guī)則的第二條:只保留最高階轴总,因此保留n2/2。根據(jù)第三條去掉和這個(gè)項(xiàng)的常數(shù)博个,則去掉1/2,最終這段代碼的時(shí)間復(fù)雜度為O(n2)怀樟。

4. 其他常見(jiàn)復(fù)雜度

除了常數(shù)階、線性階盆佣、平方階往堡、對(duì)數(shù)階,還有如下時(shí)間復(fù)雜度:

  • O(nlogn)共耍,可以稱為nlogn階

如果一段代碼的時(shí)間復(fù)雜度是 O(logn)虑灰,循環(huán)執(zhí)行 n 遍,時(shí)間復(fù)雜度就是 O(nlogn)痹兜,歸并排序穆咐、快速排序的時(shí)間復(fù)雜度都是 O(nlogn)。

  • O(√n),可以稱為平方根階
  • O(n3)对湃,可以稱為立方階
  • O(2?)崖叫,可以稱為指數(shù)階
  • O(n!),可以稱為階乘階

復(fù)雜度的比較

n logn √n nlogn n2 2? n!
5 2 2 10 25 32 120
10 3 3 30 100 1024 3628800
50 5 7 250 2500 約10^15 約3.0*10^64
100 6 10 600 10000 約10^30 約9.3*10^157
1000 9 31 9000 1000 000 約10^300 約4.0*10^2567

從上表可以看出拍柒,O(n)归露、O(logn)、O(√n )斤儿、O(nlogn )隨著n的增加剧包,復(fù)雜度提升不大,因此這些復(fù)雜度屬于效率高的算法往果,反觀O(2?)和O(n!)當(dāng)n增加到50時(shí)疆液,復(fù)雜度就突破十位數(shù)了,這種效率極差的復(fù)雜度最好不要出現(xiàn)在程序中陕贮,因此在動(dòng)手編程時(shí)要評(píng)估所寫(xiě)算法的最壞情況的復(fù)雜度堕油。

常用的時(shí)間復(fù)雜度按照耗費(fèi)的時(shí)間從小到大依次是:

O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2?) < O(n!)

最好、最壞肮之、平均掉缺、均攤時(shí)間復(fù)雜度

  • 最壞情況時(shí)間復(fù)雜度:代碼在最理想情況下執(zhí)行的時(shí)間復(fù)雜度。
  • 最好情況時(shí)間復(fù)雜度:代碼在最壞情況下執(zhí)行的時(shí)間復(fù)雜度戈擒。
  • 平均時(shí)間復(fù)雜度:用代碼在所有情況下執(zhí)行的次數(shù)的加權(quán)平均值表示眶明。
  • 均攤時(shí)間復(fù)雜度:在代碼執(zhí)行的所有復(fù)雜度情況中絕大部分是低級(jí)別的復(fù)雜度,個(gè)別情況是高級(jí)別復(fù)雜度且發(fā)生具有時(shí)序關(guān)系時(shí)筐高,可以將個(gè)別高級(jí)別復(fù)雜度均攤到低級(jí)別復(fù)雜度上搜囱。這種復(fù)雜度分析法我們就叫做均攤復(fù)雜度分析法。最典型的例子就是我們寫(xiě)一個(gè)動(dòng)態(tài)數(shù)組這樣的一個(gè)類(lèi)柑土,動(dòng)態(tài)數(shù)組每添加一個(gè)元素蜀肘,或者刪除一個(gè)元素,我們就要用到均攤復(fù)雜度分析法稽屏。

同一段代碼在不同情況下出現(xiàn)量級(jí)差別時(shí)才需要區(qū)別這四種復(fù)雜度扮宠。大多數(shù)情況下,是不需要區(qū)別分析它們的狐榔。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坛增,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子荒叼,更是在濱河造成了極大的恐慌轿偎,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件被廓,死亡現(xiàn)場(chǎng)離奇詭異坏晦,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)昆婿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)球碉,“玉大人,你說(shuō)我怎么就攤上這事仓蛆≌龆” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵看疙,是天一觀的道長(zhǎng)豆拨。 經(jīng)常有香客問(wèn)我,道長(zhǎng)能庆,這世上最難降的妖魔是什么施禾? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮搁胆,結(jié)果婚禮上弥搞,老公的妹妹穿的比我還像新娘。我一直安慰自己渠旁,他們只是感情好攀例,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著顾腊,像睡著了一般粤铭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上投慈,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天承耿,我揣著相機(jī)與錄音,去河邊找鬼伪煤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛凛辣,可吹牛的內(nèi)容都是我干的抱既。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼扁誓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼防泵!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蝗敢,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捷泞,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后寿谴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體锁右,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咏瑟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拂到。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖码泞,靈堂內(nèi)的尸體忽然破棺而出兄旬,到底是詐尸還是另有隱情,我是刑警寧澤余寥,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布领铐,位于F島的核電站,受9級(jí)特大地震影響宋舷,放射性物質(zhì)發(fā)生泄漏罐孝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一肥缔、第九天 我趴在偏房一處隱蔽的房頂上張望莲兢。 院中可真熱鬧,春花似錦续膳、人聲如沸改艇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谒兄。三九已至,卻和暖如春社付,著一層夾襖步出監(jiān)牢的瞬間承疲,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工鸥咖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留燕鸽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓啼辣,卻偏偏與公主長(zhǎng)得像啊研,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鸥拧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容