iOS算法基礎(chǔ)之算法復(fù)雜度解疑

對(duì)于一個(gè)給定的算法,我們要做兩項(xiàng)分析。第一是從數(shù)學(xué)上證明算法的正確性核芽,而在證明算法是正確的基礎(chǔ)上,第二部就是分析算法的時(shí)間復(fù)雜度酵熙。一個(gè)算法的優(yōu)劣往往通過算法復(fù)雜度來衡量轧简,算法復(fù)雜度包括時(shí)間復(fù)雜度和空間復(fù)雜度。時(shí)間復(fù)雜度是算法的所需要消耗的時(shí)間匾二,時(shí)間越短哮独,算法越好拳芙。可以對(duì)算法的代碼進(jìn)行估計(jì)皮璧,而得到算法的時(shí)間復(fù)雜度舟扎。一般來說,算法代碼簡(jiǎn)短精悍可以用來減少算法的時(shí)間復(fù)雜度悴务!

空間復(fù)雜度指的是算法程序在執(zhí)行時(shí)所需要的存儲(chǔ)空間睹限。空間復(fù)雜度可以分為以下兩個(gè)方面讯檐!

1.程序的保存所需要的存儲(chǔ)空間資源羡疗。即程序的大小别洪;

2.程序在執(zhí)行過程中所需要消耗的存儲(chǔ)空間資源叨恨,如中間變量等;

一般來說挖垛,程序的大小越小痒钝,執(zhí)行過程中消耗的資源越少,這個(gè)程序就越好痢毒!

算法復(fù)雜度統(tǒng)計(jì)方法

一個(gè)算法是由控制結(jié)構(gòu)(順序送矩、分支和循環(huán)3種)和原操作(指固有數(shù)據(jù)類型的操作)構(gòu)成的,則算法時(shí)間取決于兩者的綜合效果闸准。為了便于比較同一個(gè)問題的不同算法益愈,通常的做法是,從算法中選取一種對(duì)于所研究的問題(或算法類型)來說是基本操作的原操作夷家,以該基本操作的重復(fù)執(zhí)行的次數(shù)作為算法的時(shí)間量度蒸其。

算法執(zhí)行時(shí)間需通過依據(jù)該算法編制的程序在計(jì)算機(jī)上運(yùn)行時(shí)所消耗的時(shí)間來度量。而度量一個(gè)程序的執(zhí)行時(shí)間通常有兩種方法库快。事后統(tǒng)計(jì)的方法和事前分析估算的方法摸袁。事后統(tǒng)計(jì)方法更多的依賴于計(jì)算機(jī)的硬件、軟件等環(huán)境因素义屏,有時(shí)容易掩蓋算法本身的優(yōu)劣靠汁。因此人們常常采用事前分析估算的方法。在編寫程序前闽铐,依據(jù)統(tǒng)計(jì)方法對(duì)算法進(jìn)行估算蝶怔。

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

時(shí)間頻度是一個(gè)算法執(zhí)行所耗費(fèi)的時(shí)間,一個(gè)算法花費(fèi)的時(shí)間與算法中語句的執(zhí)行次數(shù)成正比例兄墅,哪個(gè)算法中語句執(zhí)行次數(shù)多踢星,它花費(fèi)時(shí)間就多。一個(gè)算法中的語句執(zhí)行次數(shù)稱為語句頻度或時(shí)間頻度隙咸。記為T(n)沐悦。當(dāng)輸入量n逐漸加大時(shí)成洗,時(shí)間復(fù)雜性的極限情形稱為算法的“漸近時(shí)間復(fù)雜性”。

我們常用大O表示法表示時(shí)間復(fù)雜性藏否,注意它是某一個(gè)算法的時(shí)間復(fù)雜性瓶殃。“O”表示量級(jí) (order)副签,比如說“二分檢索是 O(logn)的”,也就是說它需要“通過logn量級(jí)的步驟去檢索一個(gè)規(guī)模為n的數(shù)組”遥椿。記法 O ( f(n) )表示當(dāng) n增大時(shí),運(yùn)行時(shí)間至多將以正比于 f(n)的速度增長(zhǎng)继薛。這種漸進(jìn)估計(jì)對(duì)算法的理論分析和大致比較是非常有價(jià)值的修壕,但在實(shí)踐中細(xì)節(jié)也可能造成差異愈捅。例如遏考,一個(gè)O(n2)算法在n較小的情況下可能比 O(nlogn)算法運(yùn)行得更快。當(dāng)然蓝谨,隨著n足夠大以后灌具,具有較慢上升函數(shù)的算法必然工作得更快。

大O表示只是說有上界譬巫,由定義知如果f(n)=O(n)咖楣,那顯然成立f(n)=O(n^2),它給你一個(gè)上界芦昔,但并不是上確界诱贿,但人們?cè)诒硎镜臅r(shí)候一般都習(xí)慣表示前者。如果某個(gè)算法的復(fù)雜性到達(dá)了這個(gè)問題復(fù)雜性的下界咕缎,那就稱這樣的算法是最佳算法珠十。

在各種不同算法中,若算法中語句執(zhí)行次數(shù)為一個(gè)常數(shù)凭豪,則時(shí)間復(fù)雜度為O(1)焙蹭。另外,在時(shí)間頻度不相同時(shí)嫂伞,時(shí)間復(fù)雜度有可能相同孔厉,如T(n)=n2+3n+4與T(n)=4n2+2n+1它們的頻度不同,但時(shí)間復(fù)雜度相同帖努,都為O(n2)撰豺。

按數(shù)量級(jí)遞增排列,常見的時(shí)間復(fù)雜度有:常數(shù)階O(1),對(duì)數(shù)階O(log2n),線性階O(n), 線性對(duì)數(shù)階O(nlog2n),平方階O(n2)拼余,立方階O(n3),...污桦,k次方階O(nk),指數(shù)階O(2n)。隨著問題規(guī)模n的不斷增大姿搜,上述時(shí)間復(fù)雜度不斷增大寡润,算法的執(zhí)行效率越低捆憎。

常見的算法時(shí)間復(fù)雜度由小到大依次為:Ο(1)<O(log2n)<Ο(n)<O(nlog2n)<O(n2)<O(n3)<…<O(2n)<Ο(n!)

時(shí)間復(fù)雜度的計(jì)算

(1)找出算法中的基本語句;算法中執(zhí)行次數(shù)最多的那條語句就是基本語句梭纹,通常是最內(nèi)層循環(huán)的循環(huán)體躲惰。

(2) 計(jì)算基本語句的執(zhí)行次數(shù)的數(shù)量級(jí);只需計(jì)算基本語句執(zhí)行次數(shù)的數(shù)量級(jí)变抽,這就意味著只要保證基本語句執(zhí)行次數(shù)的函數(shù)中的最高次冪正確即可础拨,可以忽略所有低次冪和最高次冪的系數(shù)。這樣能夠簡(jiǎn)化算法分析绍载,并且使注意力集中在最重要的一點(diǎn)上:增長(zhǎng)率诡宗。

(3)用大Ο記號(hào)表示算法的時(shí)間性能。將基本語句執(zhí)行次數(shù)的數(shù)量級(jí)放入大Ο記號(hào)中击儡。如果算法中包含嵌套的循環(huán)塔沃,則基本語句通常是最內(nèi)層的循環(huán)體,如果算法中包含并列的循環(huán)阳谍,則將并列循環(huán)的時(shí)間復(fù)雜度相加蛀柴。

(4)對(duì)于一些簡(jiǎn)單的輸入輸出語句或賦值語句,近似認(rèn)為需要O(1)時(shí)間。對(duì)于順序結(jié)構(gòu),需要依次執(zhí)行一系列語句所用的時(shí)間可采用大O下"求和法則"矫夯。對(duì)于選擇結(jié)構(gòu),如if語句,它的主要時(shí)間耗費(fèi)是在執(zhí)行then字句或else字句所用的時(shí)間,需注意的是檢驗(yàn)條件也需要O(1)時(shí)間鸽疾。對(duì)于循環(huán)結(jié)構(gòu),循環(huán)語句的運(yùn)行時(shí)間主要體現(xiàn)在多次迭代中執(zhí)行循環(huán)體以及檢驗(yàn)循環(huán)條件的時(shí)間耗費(fèi),一般可用大O下"乘法法則"。乘法法則: 是指若算法的2個(gè)部分時(shí)間復(fù)雜度分別為 T1(n)=O(f(n))和 T2(n)=O(g(n)),則 T1T2=O(f(n)g(n))训貌。

對(duì)于復(fù)雜的算法,可以將它分成幾個(gè)容易估算的部分,然后利用求和法則和乘法法則技術(shù)整個(gè)算法的時(shí)間復(fù)雜度制肮。另外還有以下2個(gè)運(yùn)算法則:(1) 若g(n)=O(f(n)),則O(f(n))+ O(g(n))= O(f(n));(2) O(Cf(n)) = O(f(n)),其中C是一個(gè)正常數(shù)递沪。

for (i=1; i<=n; i++)  
   x++;  
for (i=1; i<=n; i++)  
 for (j=1; j<=n; j++)  
      x++; 

第一個(gè)for循環(huán)的時(shí)間復(fù)雜度為Ο(n)豺鼻,第二個(gè)for循環(huán)的時(shí)間復(fù)雜度為Ο(n2),則整個(gè)算法的時(shí)間復(fù)雜度為Ο(n+n2)=Ο(n2)区拳。

常見的時(shí)間復(fù)雜度說明

1拘领、O(1)
    Temp=i; i=j; j=temp;                    

以上三條單個(gè)語句的頻度均為1,該程序段的執(zhí)行時(shí)間是一個(gè)與問題規(guī)模n無關(guān)的常數(shù)樱调。算法的時(shí)間復(fù)雜度為常數(shù)階约素,記作T(n)=O(1)。注意:如果算法的執(zhí)行時(shí)間不隨著問題規(guī)模n的增加而增長(zhǎng)笆凌,即使算法中有上千條語句圣猎,其執(zhí)行時(shí)間也不過是一個(gè)較大的常數(shù)。此類算法的時(shí)間復(fù)雜度是O(1)乞而。

2送悔、O(n2)
sum=0;                       (1)
for(i=1;i<=n;i++)            (n+1)
  for(j=1;j<=n;j++)          (n^2)
    sum++;                  (n^2)

解:因?yàn)棣?2n2+n+1)=n2(Θ即:去低階項(xiàng)欠啤,去掉常數(shù)項(xiàng)荚藻,去掉高階項(xiàng)的常參得到),所以T(n)=O(n2)洁段;

for (i=1;i<n;i++)  
 {   
   y=y+1;         ①     
   for (j=0;j<=(2*n);j++)      
      x++;         ②        
 }  

解: 語句1的頻度是n-1应狱,語句2的頻度是(n-1)*(2n+1)=2n2-n-1。f(n)=2n2-n-1+(n-1)=2n2-2祠丝;又Θ(2n2-2)=n2疾呻,該程序的時(shí)間復(fù)雜度T(n)=O(n2)。

一般情況下写半,對(duì)步進(jìn)循環(huán)語句只需考慮循環(huán)體中語句的執(zhí)行次數(shù)岸蜗,忽略該語句中步長(zhǎng)加1、終值判別叠蝇、控制轉(zhuǎn)移等成分璃岳,當(dāng)有若干個(gè)循環(huán)語句時(shí),算法的時(shí)間復(fù)雜度是由嵌套層數(shù)最多的循環(huán)語句中最內(nèi)層語句的頻度f(n)決定的蟆肆。

3矾睦、O(n)
a=0;  
b=1;                      ①  
for (i=1;i<=n;i++)        ②  
{    
 s=a+b;    ③  
 b=a;    ⊙坠Α④    
 a=s;     ⑤  
} 

解: 語句1的頻度:2,
語句2的頻度: n,
語句3的頻度: n-1,
語句4的頻度:n-1,
語句5的頻度:n-1,
T(n)=2+n+3(n-1)=4n-1=O(n).

4缓溅、O(log2n)
i=1;       ①  
while (i<=n)  
  i=i*2;   ② 

解: 語句1的頻度是1,
設(shè)語句2的頻度是f(n), 則:2^f(n)<=n;f(n)<=log2n
取最大值f(n)=log2n,
T(n)=O(log2n )

5蛇损、O(n3)
for(i=0;i<n;i++)  
 {    
    for(j=0;j<i;j++)    
    {  
     for(k=0;k<j;k++)  
        x=x+2;    
    }  
 }

解:3層循環(huán),由上可知復(fù)雜度為O(n3).

常用的算法的時(shí)間復(fù)雜度和空間復(fù)雜度

同一個(gè)算法處理不同的輸入數(shù)據(jù)所消耗的資源也可能不同坛怪,所以分析一個(gè)算法的復(fù)雜度時(shí)淤齐,主要有三種情況可以考慮,最差情況(Worst Case)下的袜匿,平均情況(Average Case)的更啄, 最好情況(Best Case)下的。我們查找一個(gè)有n個(gè)隨機(jī)數(shù)字?jǐn)?shù)組中的某個(gè)數(shù)字居灯,最好的情況是第一個(gè)數(shù)字就是祭务,那么算法的時(shí)間復(fù)雜度為O(1),但也有可能這個(gè)數(shù)字就在最后一個(gè)位置上待著怪嫌,那么算法的時(shí)間復(fù)雜度就是O(n)义锥,這是最壞的一種情況了。最壞情況運(yùn)行時(shí)間是一種保證岩灭,那就是運(yùn)行時(shí)間將不會(huì)再壞了拌倍。在應(yīng)用中,這是一種最重要的需求,通常柱恤,除非特別指定数初,我們提到的運(yùn)行時(shí)間都是最壞情況的運(yùn)行時(shí)間。

平均運(yùn)行時(shí)間也就是從概率的角度看梗顺,這個(gè)數(shù)字在每一個(gè)位置的可能性是相同的妙真,所以平均的查找時(shí)間為n/2次后發(fā)現(xiàn)這個(gè)目標(biāo)元素。平均情況更能反映大多數(shù)情況下算法的表現(xiàn)荚守。平均情況分析就是對(duì)所有輸入尺寸為n的輸入珍德,讓算法運(yùn)轉(zhuǎn)一遍,然后取它們的平均值矗漾。當(dāng)然锈候,實(shí)際中不可能將所有可能的輸入都運(yùn)行一遍,因此平均情況通常指的是一種數(shù)學(xué)期望值敞贡,而計(jì)算數(shù)學(xué)期望值則需要對(duì)輸入的分布情況進(jìn)行假設(shè)泵琳,一般都是通過運(yùn)行一定數(shù)量的實(shí)驗(yàn)數(shù)據(jù)后估算出來的。

考慮最好情況的復(fù)雜度更是沒有意義誊役。幾乎所有的算法你都可以稍微修改一下获列,以獲得很好的最好情況下的復(fù)雜度(要看輸入數(shù)據(jù)的結(jié)構(gòu),可以是O(1)蛔垢。怎樣修改呢? 預(yù)先計(jì)算好某一輸入的答案击孩,在算法的開始部分判斷輸入,如果符合鹏漆,給出答案巩梢。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市艺玲,隨后出現(xiàn)的幾起案子括蝠,更是在濱河造成了極大的恐慌,老刑警劉巖饭聚,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忌警,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡秒梳,警方通過查閱死者的電腦和手機(jī)法绵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來端幼,“玉大人礼烈,你說我怎么就攤上這事∑排埽” “怎么了此熬?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我犀忱,道長(zhǎng)募谎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任阴汇,我火速辦了婚禮数冬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘搀庶。我一直安慰自己拐纱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布哥倔。 她就那樣靜靜地躺著秸架,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咆蒿。 梳的紋絲不亂的頭發(fā)上东抹,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音沃测,去河邊找鬼缭黔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蒂破,可吹牛的內(nèi)容都是我干的馏谨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼寞蚌,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼田巴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挟秤,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎抄伍,沒想到半個(gè)月后艘刚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡截珍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年攀甚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岗喉。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡秋度,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钱床,到底是詐尸還是另有隱情荚斯,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站事期,受9級(jí)特大地震影響滥壕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兽泣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一绎橘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧唠倦,春花似錦称鳞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至枷餐,卻和暖如春靶瘸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背毛肋。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工怨咪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人润匙。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓诗眨,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親孕讳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匠楚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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