<<大話數(shù)據(jù)結(jié)構(gòu)>>之時間復(fù)雜度

程序猿可以讓步,卻不可以退縮,可以羞澀,卻不可以軟弱,總之,程序員必須是勇敢的。
大話數(shù)據(jù)結(jié)構(gòu)


時間復(fù)雜度序言


當(dāng)前兩天我寫完<<大話數(shù)據(jù)結(jié)構(gòu)>>的序言的時候,我就在想,我該如何把從大話數(shù)據(jù)結(jié)構(gòu)中對應(yīng)用開發(fā)人員有用的知識提煉出來?我是該如同課本一樣把所有的知識羅列個遍?還是如何如何,我想如果我把所有的東西都羅列出來,那還不如讓廣大的讀者去自己看這本書呢,畢竟我這小渣渣的層次面還跟不上程杰大神呢,幽默度更不用說了,所以我想了幾天 決定把對開發(fā)人員有用的整理出來,其實(shí)也是為了自己以后能夠快速地找到我想要的知識點(diǎn).利人利己的事情,何樂而不為呢?


時間復(fù)雜度的概念以及實(shí)際作用


計(jì)算機(jī)科學(xué)中,算法的時間復(fù)雜度是一個函數(shù),它定量描述了該算法的運(yùn)行時間。這是一個關(guān)于代表算法輸入值的字符串的長度的函數(shù)。時間復(fù)雜度常用大O符號表述,不包括這個函數(shù)的低階項(xiàng)和首項(xiàng)系數(shù)。使用這種方式時,時間復(fù)雜度可被稱為是漸近的,它考察當(dāng)輸入值大小趨近無窮時的情況。

說白了,就是對函數(shù)或者方法的復(fù)雜程度的度量.那么我們什么時候使用這個時間復(fù)雜度呢?在實(shí)際中,我們或多或少都要寫一些方法或者函數(shù),但是如果函數(shù)的時間復(fù)雜度過大,就會影響到整個項(xiàng)目或者工程的運(yùn)行,耗損不必要的內(nèi)存空間,影響用戶的體驗(yàn)效果,一旦用戶的體驗(yàn)效果不好,那么就是老一套了,該需求,改需求再改需求...但是我們需要改動那一些函數(shù)或者方法呢?這就需要到我們的"時間復(fù)雜度"相關(guān)的知識了.(當(dāng)然了,空間復(fù)雜度也是需要的,但是我還沒看到那,所以,見諒~)


算法時間復(fù)雜度的定義


定義:在進(jìn)行算法分析時候,語句總的執(zhí)行次數(shù)T(n)是關(guān)于問題規(guī)模n的函數(shù),進(jìn)而分型T(n)隨著n的變化情況并確定T(n)的數(shù)量級.算法的時間復(fù)雜度,也就是算法的時間度量記作:T(n)=O(f(n)).它表示隨著問題規(guī)模n的增大,算法執(zhí)行時間的增長率和f(n)的增長率相同,稱作算法的漸近時間復(fù)雜度,簡稱時間復(fù)雜度.其中f(n)是問題規(guī)模n的某個函數(shù).

這里用大寫的O( )來體現(xiàn)算法時間復(fù)雜度的記法,我們稱之為大O記法.


分析一個函數(shù)或者算法的時間復(fù)雜度


分析一個函數(shù)或者算法的時間復(fù)雜度,其實(shí)就是 推導(dǎo)大O階

推導(dǎo)大O階:
1.用常熟1取代運(yùn)行時間中的所有加法常數(shù).
2.在修改后的運(yùn)行次數(shù)函數(shù)中,只保留最高階項(xiàng).
3.如果最高階項(xiàng)存在且不是1,則去除與這個像相乘的常數(shù).
得到的結(jié)果就是大O階.

正如書中所講的一樣,這就是游戲攻略,我們拿著這個游戲攻略開始戰(zhàn)斗吧.


比較常見的大O階分析


    1. 常數(shù)階
      我們來看下面的這個算法,作為程序員的我們可能看一眼就知道它是一個順序結(jié)構(gòu),并且執(zhí)行了三次.那么它的時間復(fù)雜度是不是就是常數(shù)3呢?因?yàn)閳?zhí)行了三次呀,這可是大錯特錯了.
      我們來看推導(dǎo)大O階的方法,首先運(yùn)行次數(shù)是3,我們根據(jù)游戲攻略的第一步,就是要把常數(shù)項(xiàng)3改成1,再根據(jù)第二步和第三步,保留最高項(xiàng),發(fā)現(xiàn)根本沒有最高項(xiàng),所以這個算法的時間復(fù)雜度為O(1).當(dāng)然了,只有順序結(jié)構(gòu)的時候,不管你執(zhí)行多少次,時間復(fù)雜度統(tǒng)統(tǒng)是O(1),也就是常數(shù)階.當(dāng)然了,分支結(jié)構(gòu)也是一樣的不管條件是真或者假,你都會發(fā)現(xiàn)整個分支結(jié)構(gòu)只是執(zhí)行了一次,所以,跟順序結(jié)構(gòu)大同小異,時間復(fù)雜度也是O(1).

順序結(jié)構(gòu)

    //順序結(jié)構(gòu)
    int sum =0, n= 100;//執(zhí)行一次
    
    sum = (1+n)/2;//執(zhí)行一次
    
    NSLog(@"%d",sum);//執(zhí)行一次

分支結(jié)構(gòu)

    //分支結(jié)構(gòu)
    
    //整個分支結(jié)構(gòu)不管條件如何都只執(zhí)行一次
    if (/* DISABLES CODE */ (1) != 2) {
        
        NSLog(@"1真的不等于2幺~");//執(zhí)行一次
        
    }else{
    
        NSLog(@"1等于2");//執(zhí)行一次
    
    }

    1. 線性階
      下面這是一個for循環(huán),那么它的時間復(fù)雜度又是多少呢?首先循環(huán)體就是一個執(zhí)行一次的循環(huán)體,總共執(zhí)行了n次,那么執(zhí)行次數(shù)就是f(n) =n,啟動我們的游戲攻略三部曲知道,時間復(fù)雜度就是為O(n).具體的步驟就不詳細(xì)說了,因?yàn)樘唵瘟瞬皇?

for循環(huán)結(jié)構(gòu)

    for (int i = 0; i< n; i++) {
        
        NSLog(@"執(zhí)行一次");//執(zhí)行一次
        
    }
  • 3.對數(shù)階
    來來來,接著看這個while循環(huán)結(jié)構(gòu),我們不難發(fā)現(xiàn),當(dāng)count大于n的時候,循環(huán)體就會結(jié)束,循環(huán)體中count不斷的乘以2,那么執(zhí)行次數(shù)是多少呢? 2^x = n 可得到 x = log2n;所以根據(jù)游戲攻略我們可以知道這個while循環(huán)體的時間復(fù)雜度是 O(log n);感覺自己看到這都能困了,嘿嘿,懵了,這里要著重看一下.

while循環(huán)結(jié)構(gòu)

    int count = 1;
    
    while (count < n) {
         
        count = count * 2;//執(zhí)行一次
        
    }

  • 4.平方階

實(shí)際應(yīng)用中肯定不能像上面那么只有單個結(jié)構(gòu),可能有兩種或者兩種以上的結(jié)構(gòu),下面看一下兩個for循環(huán)嵌套的時間復(fù)雜度又是如何呢? 我們先看一個特殊的嵌套,下面的這個嵌套是兩層都進(jìn)行n次循環(huán),那么總的執(zhí)行次數(shù)函數(shù)就是 f(n) = n^2;接著再根據(jù)我們的游戲攻略一頓計(jì)算,知道我們的時間復(fù)雜度是 O(n^2 );

兩層都執(zhí)行n次的for循環(huán)

    for (int i = 0; i< n; i++) {
        
        for (int  j = 0; j< n; i++) {
            
            NSLog(@"這個地方是時間復(fù)雜度為O(1)的算法");
            
        }
        
    }

如果是下面的這種呢?外層循環(huán)n次,內(nèi)層循環(huán)m次,我們又該如何求解復(fù)雜度呢?其實(shí)跟上面是大同小異的,我們只需要把上面的其中一個n換成m就好了,所以時間復(fù)雜度為O(m*n );

    for (int i = 0; i< n; i++) {
        
        for (int j = 0; j< m; i++) {
            
            NSLog(@"這個地方是時間復(fù)雜度為O(1)的算法");
            
        }
        
    }
    

那么,再看一下下面的這個嵌套,我們分析一下它總共執(zhí)行幾次,由于當(dāng)i = 0時,內(nèi)循環(huán)執(zhí)行n此,當(dāng)n = 1時, 執(zhí)行了 n - 1 次, ...當(dāng) i = n-1 時, 執(zhí)行了1次,所以總的執(zhí)行次數(shù)為:

</b>

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

根據(jù)我們的游戲秘籍的三部曲,我們可以分析出來,時間復(fù)雜度為 O( n^2 );

    for (int i = 0; i< n; i++) {
        
        for (int j = i; j< n; j++) {
            
            NSLog(@"這個地方是時間復(fù)雜度為O(1)的算法");
            
        }
        
    }
  • 5.函數(shù)的調(diào)用
    我們看一下 如何我們調(diào)用函數(shù)或者方法,那么該如何計(jì)算時間復(fù)雜度呢?這里我調(diào)用OC中的方法,然后就是下面的這個,其實(shí)我們只要用嵌套的眼光看待就行,根據(jù)我們的游戲秘籍 不難得到下面的這個時間復(fù)雜度是 O (n ^2);如果函數(shù)或者方法中有其他的按照嵌套的規(guī)律來計(jì)算時間復(fù)雜度就好;額
    for (int i = 0; i< n; i++) {
        
        for (int j = 0; j< n; j++) {
            

            [self function];
        }
        
    }
    


-(void)function{

    NSLog(@"這個地方是時間復(fù)雜度為O(1)的算法");

}


常見的時間復(fù)雜度


我就直接上圖了,主要是比較集中常見的時間復(fù)雜度的大小.


幾種時間復(fù)雜度的大小.png


時間復(fù)雜度總結(jié) :時間復(fù)雜度對我們開發(fā)過程中做算法以及項(xiàng)目的優(yōu)化有著極大的幫助.雖然我們作為的是一個開發(fā)人員,不是一個科研人員,但是,我們了解時間復(fù)雜度的概念和作用是有著很大的優(yōu)勢的,時間復(fù)雜度主要就是掌握游戲攻略三部曲就好了.文筆不好如果有什么問題或者意見,歡迎評論.謝謝.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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