算法的時間復(fù)雜度與空間復(fù)雜度

概述

執(zhí)行效率是考量一個算法是否高效的主要指標(biāo)藻雌。然而時間、空間復(fù)雜度又是衡量算法執(zhí)行效率的主要維度

一疹吃、事后統(tǒng)計法的局限

以前通過統(tǒng)計蹦疑、監(jiān)控實際代碼的運(yùn)行就能夠獲取算法執(zhí)行的時間和占用的內(nèi)存大小西雀。這種事后統(tǒng)計方法雖然能夠評估算法的執(zhí)行效率萨驶,但還是存在諸多缺陷。

  1. 測試結(jié)果非常依賴測試環(huán)境

    測試環(huán)境中硬件配置的不同對測試結(jié)果會產(chǎn)生很大的影響艇肴。

  2. 測試結(jié)果受數(shù)據(jù)規(guī)模的影響較大

    對于同一個算法而言腔呜,測試數(shù)據(jù)量的大小不同,其所得出的性能測試結(jié)果也會不同再悼。

二核畴、大 O復(fù)雜度表示法

如下一段代碼:

public int sum(int n){
     1   int sum = 0;
     2   for(int i = 0; i<n ; i++){
     3       sum = sum +1;
        }
        return sum;
    }

假設(shè)每一段代碼的執(zhí)行時間單位為T,那么第1行代碼執(zhí)行時間為T冲九,第3行代碼由于執(zhí)行了n次谤草,那么執(zhí)行時間為nT所以這段代碼的總執(zhí)行時間為(n+1)T,由此可知:所有代碼的執(zhí)行時間T(n)與每行代碼的執(zhí)行次數(shù)n成正比莺奸。

接下來再看一段代碼

public int sum(int n){
     1   int sum = 0;
     2   for (int i = 0 ; i<= n ; ++i){
     3       for (int j = 0 ; j<= n ; ++j){
     4           sum = sum + i*j;
            }
        }
        return sum;
    }

這里每行代碼的執(zhí)行時間單位仍舊為T丑孩,那么第1行代碼的執(zhí)行時間為T,第4行代碼由于執(zhí)行了n2次灭贷,所以執(zhí)行時間為n2T温学。因此,整段代碼的執(zhí)行時間為:(n2+1)T 甚疟。

將以上規(guī)律總結(jié)成一個公式仗岖,就是我們所知的大O表達(dá)式

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

其中:T(n)代表代碼所執(zhí)行的時間览妖;n表示數(shù)據(jù)規(guī)模的大性簟;f(n)表示每行代碼執(zhí)行的次數(shù)總和讽膏。而公式中的O則表明了代碼的執(zhí)行時間T(n)與 f(n) 表達(dá)式成正比檩电。

大O復(fù)雜度分析表示法,并不具體表示代碼真正的執(zhí)行時間,而是表示代碼執(zhí)行時間隨數(shù)據(jù)規(guī)模增長的變化趨勢是嗜,一般叫作漸進(jìn)時間復(fù)雜度(asymptotic time complexity)愈案,簡稱時間復(fù)雜度。同時鹅搪,當(dāng)n趨于無限大的時候站绪,我們就可以忽略公式中的低階、常量丽柿、與系數(shù)三部分恢准。只需記錄一個最大的量級,如 T(n) = O(2n2 + 2n +3) 我們省略掉其中的低階甫题、常量馁筐、與系數(shù)所得出的最終結(jié)果為:T(n) = O(n2)。因此以上兩段代碼的時間復(fù)雜度就可以記為 : T(n) = O(n) 坠非;T(n) = O(n2)敏沉。

三、時間復(fù)雜度分析

  1. 只關(guān)注循環(huán)執(zhí)行次數(shù)最多的一段代碼:

    關(guān)于這一點(diǎn)炎码,之前的代碼示列就是很好的說明盟迟,這里不再贅述。

  2. 加法法則:總復(fù)雜度等于量級最大的那段代碼的復(fù)雜度

    比如如下一段代碼:

    public int sum(int n){
            
            int sumOne = 0;
            for (int i = 0; i <= 1000 ; ++i){
       1         sumOne += i;
            }
    
            int sumTwo = 0;
            for (int i= 0; i< n ; ++i){
        2        sumTwo += i;
            }
    
            int sumThree = 0;
            for (int i = 0; i< n ; ++i){
                for (int j = 0 ; j < n ;++j){
        3            sumThree = sumThree + i *j;
                }
            }
    
            return sumOne + sumTwo + sumThree;
        }
    

    這段代碼共分為三個部分潦闲,分別求sumOne攒菠、sumTwo、sumThree歉闰。我們可以分別解析每一個部分的時間復(fù)雜度辖众,然后再從他們之中選取一個量級最大的作為整段代碼的復(fù)雜度。

第一段代碼執(zhí)行了1000次和敬,所以其代表的是一個常量級的執(zhí)行時間凹炸,跟n的規(guī)模無關(guān),可以將其忽略掉概龄。

第二段代碼和第三段代碼分別執(zhí)行了 n 次和 n2次还惠,所以他們的時間復(fù)雜度分別為O(n) 和O(n2)。

綜合這三段代碼的時間復(fù)雜度私杜,我們?nèi)∑渲凶畲蟮牧考壊霞敲凑未a的復(fù)雜度就為:O(n2)

因此將上述這個公式抽象一下就可以得出:

如果:T1(n) = O(f(n)),T2(n)=O(g(n))衰粹;那么 T(n) = T1(n)+T2(n) = max(O(f(n)),O(g(n)))=O(max(f(n),g(n)))

  1. 乘法法則:嵌套代碼的復(fù)雜度等于嵌套內(nèi)外代碼復(fù)雜度的乘積

    如果T1(n) = O(f(n))锣光,T2(n) = O(g(n));那么 T(n) = T1(n) x T2(n) = O(f(n)) x O(g(n) = O(f(n) x g(n))

public int sum(int n){

        int result = 0;

        for (int i = 0 ; i < n ;++i){
   1         result = result + subSum(n);
        }

        return result;
    }

    public int subSum(int n){
        int subSum = 0;

        for (int j = 0 ; j < n ; ++j){
    2        subSum += j;
        }

        return subSum;
    }

其中:第一段铝耻,第二段代碼都是執(zhí)行了n次誊爹,時間復(fù)雜度都是 T(n) = O(n)蹬刷。但由于第二段代碼是嵌套在第一段代碼之中執(zhí)行的,因此整個代碼的時間復(fù)雜度應(yīng)為:T(n) = T1(n) x T2(n) = O(n) x O(n) = O(n2)

四频丘、常見時間復(fù)雜度

?

多項式量級 非多項式量級
常量階O(1) 指數(shù)階O(2n)
對數(shù)階O(logn) 階乘階O(n!)
線性階O(n)
線性對數(shù)階O(nlogn)
平方階O(n2)办成、立方階O(n3)、··· 搂漠、k次方階O(nk)
  1. 常量階 O(1)

    一般來說迂卢,只要算法中不存在循環(huán)語句、遞歸語句桐汤、即使有成千上萬行代碼而克,其時間復(fù)雜度仍舊是O(1)

  1. 對數(shù)階O(logn),線性對數(shù)階O(nlogn)

    int i = 1;
    while( i <= n){
        i = i * 2;
    }
    

    如上一段代碼中怔毛,i 的取值為 20员萍, 21, 22拣度,···· 碎绎, 2x-1, 2x 成等比隊列蜡娶。要想知道這段代碼執(zhí)行了多少次混卵,求出 2x = n 的結(jié)果就行。 x = log2n窖张,所以這段代碼的時間復(fù)雜度就是 O( log2n),這里忽視掉底數(shù)蚁滋,那么所有的對數(shù)階時間復(fù)雜度可以表示為O(logn)宿接。

  2. O(m+n)、O(m * n)

     public int sum(int m , int n){
    
            int sumOne = 0;
    
            for (int i = 0 ; i<= m ; ++i){
                sumOne += m;
            }
    
            int sumTwo = 0;
    
            for (int j = 0 ; j<= n ; ++j){
                sumTwo += j;
            }
    
            return sumOne+sumTwo;
        }
    

    上述代碼中辕录,復(fù)雜度取決于兩個數(shù)據(jù)規(guī)模 m 與 n睦霎,因此無法事先評估m(xù) 與 n 誰的量級更大,因此加法法則在這里不適用走诞。因此上段代碼的時間復(fù)雜度即為O(m+n)副女。但是乘法法則依舊適用:T1(m) x T2(n) = O(f(m) x f(n))。

五蚣旱、空間復(fù)雜度分析

空間復(fù)雜度就是漸進(jìn)空間復(fù)雜度(asymptotic space complexity),表示算法的存儲空間與數(shù)據(jù)規(guī)模之間的增長關(guān)系碑幅。

 public void initArray(int n){
     1   int[] arr = new int[n];
        for (int i = 0 ; i<= n ; ++i){
            arr[i] = i * i;
        }
    }

如上述代碼所示,我們在第一行代碼中申請了一個大小為n的int類型數(shù)組塞绿,除此之外其他的代碼都沒有占據(jù)更多的空間沟涨,因此整段代碼的空間復(fù)雜度就是O(n),相對于時間復(fù)雜度而言异吻,空間復(fù)雜度的分析要更為簡單裹赴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子棋返,更是在濱河造成了極大的恐慌延都,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件睛竣,死亡現(xiàn)場離奇詭異窄潭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)酵颁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門嫉你,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人躏惋,你說我怎么就攤上這事幽污。” “怎么了簿姨?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵距误,是天一觀的道長。 經(jīng)常有香客問我扁位,道長准潭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任域仇,我火速辦了婚禮刑然,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘暇务。我一直安慰自己泼掠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布垦细。 她就那樣靜靜地躺著择镇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪括改。 梳的紋絲不亂的頭發(fā)上腻豌,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機(jī)與錄音嘱能,去河邊找鬼吝梅。 笑死,一個胖子當(dāng)著我的面吹牛焰檩,可吹牛的內(nèi)容都是我干的憔涉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼析苫,長吁一口氣:“原來是場噩夢啊……” “哼兜叨!你這毒婦竟也來了穿扳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤国旷,失蹤者是張志新(化名)和其女友劉穎矛物,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跪但,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡履羞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了屡久。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忆首。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖被环,靈堂內(nèi)的尸體忽然破棺而出糙及,到底是詐尸還是另有隱情,我是刑警寧澤筛欢,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布浸锨,位于F島的核電站,受9級特大地震影響版姑,放射性物質(zhì)發(fā)生泄漏柱搜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一剥险、第九天 我趴在偏房一處隱蔽的房頂上張望聪蘸。 院中可真熱鬧,春花似錦炒嘲、人聲如沸宇姚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至阱持,卻和暖如春夭拌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衷咽。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工鸽扁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人镶骗。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓桶现,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鼎姊。 傳聞我的和親對象是個殘疾皇子骡和,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

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