一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

我們應(yīng)該如何去衡量不同算法之間的優(yōu)劣呢?

算法與數(shù)據(jù)結(jié)構(gòu) ? 來源:lq ? 2018-12-19 11:08 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

算法(Algorithm)是指用來操作數(shù)據(jù)、解決程序問題的一組方法。對于同一個問題,使用不同的算法,也許最終得到的結(jié)果是一樣的,比如排序就有前面的十大經(jīng)典排序和幾種奇葩排序,雖然結(jié)果相同,但在過程中消耗的資源和時間卻會有很大的區(qū)別,比如快速排序與猴子排序:)。

那么我們應(yīng)該如何去衡量不同算法之間的優(yōu)劣呢?

主要還是從算法所占用的「時間」和「空間」兩個維度去考量。

時間維度:是指執(zhí)行當(dāng)前算法所消耗的時間,我們通常用「時間復(fù)雜度」來描述。

空間維度:是指執(zhí)行當(dāng)前算法需要占用多少內(nèi)存空間,我們通常用「空間復(fù)雜度」來描述。

本小節(jié)將從「時間」的維度進行分析。

什么是大O

當(dāng)看「時間」二字,我們肯定可以想到將該算法程序運行一篇,通過運行的時間很容易就知道復(fù)雜度了。

這種方式可以嗎?當(dāng)然可以,不過它也有很多弊端。

比如程序員小吳的老式電腦處理10w數(shù)據(jù)使用冒泡排序要幾秒,但讀者的iMac Pro 可能只需要0.1s,這樣的結(jié)果誤差就很大了。更何況,有的算法運行時間要很久,根本沒辦法沒時間去完整的運行,還是比如猴子排序:)。

那有什么方法可以嚴(yán)謹(jǐn)?shù)倪M行算法的時間復(fù)雜度分析呢?

有的!

「 遠古 」的程序員大佬們提出了通用的方法:「 大O符號表示法 」,即T(n) = O(f(n))。

其中 n 表示數(shù)據(jù)規(guī)模 ,O(f(n))表示運行算法所需要執(zhí)行的指令數(shù),和f(n)成正比。

上面公式中用到的 Landau符號是由德國數(shù)論學(xué)家保羅·巴赫曼(Paul Bachmann)在其1892年的著作《解析數(shù)論》首先引入,由另一位德國數(shù)論學(xué)家艾德蒙·朗道(Edmund Landau)推廣。Landau符號的作用在于用簡單的函數(shù)來描述復(fù)雜函數(shù)行為,給出一個上或下(確)界。在計算算法復(fù)雜度時一般只用到大O符號,Landau符號體系中的小o符號、Θ符號等等比較不常用。這里的O,最初是用大寫希臘字母,但現(xiàn)在都用大寫英語字母O;小o符號也是用小寫英語字母o,Θ符號則維持大寫希臘字母Θ。

注:本文用到的算法中的界限指的是最低的上界。

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

我們先從常見的時間復(fù)雜度量級進行大O的理解:

常數(shù)階O(1)

線性階O(n)

平方階O(n2)

對數(shù)階O(logn)

線性對數(shù)階O(nlogn)

O(1)

無論代碼執(zhí)行了多少行,其他區(qū)域不會影響到操作,這個代碼的時間復(fù)雜度都是O(1)

1voidswapTwoInts(int&a,int&b){2inttemp=a;3a=b;4b=temp;5}

O(n)

在下面這段代碼,for循環(huán)里面的代碼會執(zhí)行 n 遍,因此它消耗的時間是隨著 n 的變化而變化的,因此可以用O(n)來表示它的時間復(fù)雜度。

1intsum(intn){2intret=0;3for(inti=0;i<=?n?;?i?++){4??????ret?+=?i;5???}6???return?ret;7}

特別一提的是 c * O(n) 中的 c 可能小于 1 ,比如下面這段代碼:

1voidreverse(string&s){2intn=s.size();3for(inti=0;i

O(n2)

當(dāng)存在雙重循環(huán)的時候,即把 O(n) 的代碼再嵌套循環(huán)一遍,它的時間復(fù)雜度就是 O(n2) 了。

1voidselectionSort(intarr[],intn){ 2for(inti=0;i

這里簡單的推導(dǎo)一下

當(dāng) i = 0 時,第二重循環(huán)需要運行 (n - 1) 次

當(dāng) i = 1 時,第二重循環(huán)需要運行 (n - 2) 次

。。。。。。

不難得到公式:

1(n-1)+(n-2)+(n-3)+...+02=(0+n-1)*n/23=O(n^2)

當(dāng)然并不是所有的雙重循環(huán)都是 O(n2),比如下面這段輸出 30n 次 Hello,五分鐘學(xué)算法:)的代碼。

1voidprintInformation(intn){2for(inti=1;i<=?n?;?i++)3????????for?(int?j?=?1?;?j?<=?30?;?j?++)4???????????cout<

O(logn)

1intbinarySearch(intarr[],intn,inttarget){ 2intl=0,r=n-1; 3while(l<=?r)?{ 4????int?mid?=?l?+?(r?-?l)?/?2; 5????if?(arr[mid]?==?target)?return?mid; 6????if?(arr[mid]?>target)r=mid-1; 7elsel=mid+1; 8} 9return-1;10}

在二分查找法的代碼中,通過while循環(huán),成 2 倍數(shù)的縮減搜索范圍,也就是說需要經(jīng)過 log2^n 次即可跳出循環(huán)。

同樣的還有下面兩段代碼也是 O(logn) 級別的時間復(fù)雜度。

1//整形轉(zhuǎn)成字符串 2stringintToString(intnum){ 3strings=""; 4//n經(jīng)過幾次“除以10”的操作后,等于0 5while(num){ 6s+='0'+num%10; 7num/=10; 8} 9reverse(s)10returns;11}1voidhello(intn){2//n除以幾次2到13for(intsz=1;sz

O(nlogn)

將時間復(fù)雜度為O(logn)的代碼循環(huán)N遍的話,那么它的時間復(fù)雜度就是 n * O(logn),也就是了O(nlogn)。

1voidhello(){2for(m=1;m

上面講述了與復(fù)雜度有關(guān)的大 O 表示法和常見的時間復(fù)雜度量級,這篇文章來講講另外幾種復(fù)雜度: 遞歸算法的時間復(fù)雜度(recursive algorithm time complexity),最好情況時間復(fù)雜度(best case time complexity)、最壞情況時間復(fù)雜度(worst case time complexity)、平均時間復(fù)雜度(average case time complexity)和均攤時間復(fù)雜度(amortized time complexity)。

遞歸算法的時間復(fù)雜度

如果遞歸函數(shù)中,只進行一次遞歸調(diào)用,遞歸深度為depth;

在每個遞歸的函數(shù)中,時間復(fù)雜度為T;

則總體的時間復(fù)雜度為O(T * depth)。

在前面的學(xué)習(xí)中,歸并排序 與 快速排序 都帶有遞歸的思想,并且時間復(fù)雜度都是O(nlogn) ,但并不是有遞歸的函數(shù)就一定是 O(nlogn) 級別的。從以下兩種情況進行分析。

① 遞歸中進行一次遞歸調(diào)用的復(fù)雜度分析

二分查找法

1intbinarySearch(intarr[],intl,intr,inttarget){ 2if(l>r)return-1; 3 4intmid=l+(r-l)/2; 5if(arr[mid]==target)returnmid; 6elseif(arr[mid]>target) 7returnbinarySearch(arr,l,mid-1,target);//左邊 8else 9returnbinarySearch(arr,mid+1,r,target);//右邊10}

比如在這段二分查找法的代碼中,每次在 [ l , r ] 范圍中去查找目標(biāo)的位置,如果中間的元素arr[mid]不是target,那么判斷arr[mid]是比target大 還是 小 ,進而再次調(diào)用binarySearch這個函數(shù)。

在這個遞歸函數(shù)中,每一次沒有找到target時,要么調(diào)用 左邊 的binarySearch函數(shù),要么調(diào)用 右邊 的binarySearch函數(shù)。也就是說在此次遞歸中,最多調(diào)用了一次遞歸調(diào)用而已。根據(jù)數(shù)學(xué)知識,需要log2n次才能遞歸到底。因此,二分查找法的時間復(fù)雜度為 O(logn)。

求和

1intsum(intn){2if(n==0)return0;3returnn+sum(n-1)4}

在這段代碼中比較容易理解遞歸深度隨輸入 n 的增加而線性遞增,因此時間復(fù)雜度為 O (n)。

求冪

1//遞歸深度:logn2//時間復(fù)雜度:O(logn)3doublepow(doublex,intn){4if(n==0)return1.0;56doublet=pow(x,n/2);7if(n%2)returnx*t*t;8returnt*t;9}

遞歸深度為logn,因為是求需要除以 2 多少次才能到底。

② 遞歸中進行多次遞歸調(diào)用的復(fù)雜度分析

遞歸算法中比較難計算的是多次遞歸調(diào)用。

先看下面這段代碼,有兩次遞歸調(diào)用。

1//O(2^n)指數(shù)級別的數(shù)量級,后續(xù)動態(tài)規(guī)劃的優(yōu)化點2intf(intn){3if(n==0)return1;4returnf(n-1)+f(n-1);5}

遞歸樹中節(jié)點數(shù)就是代碼計算的調(diào)用次數(shù)。

比如 當(dāng)n = 3時,調(diào)用次數(shù)計算公式為

1 + 2 + 4 + 8 = 15

一般的,調(diào)用次數(shù)計算公式為

2^0 + 2^1 + 2^2 + …… + 2^n= 2^(n+1) - 1= O(2^n)

與之有所類似的是 歸并排序 的遞歸樹,區(qū)別點在于

1. 上述例子中樹的深度為n,而 歸并排序 的遞歸樹深度為logn。

2. 上述例子中每次處理的數(shù)據(jù)規(guī)模是一樣的,而在 歸并排序 中每個節(jié)點處理的數(shù)據(jù)規(guī)模是逐漸縮小的

因此,在如 歸并排序 等排序算法中,每一層處理的數(shù)據(jù)量為 O(n) 級別,同時有l(wèi)ogn層,時間復(fù)雜度便是 O(nlogn)。

最好、最壞情況時間復(fù)雜度

最好、最壞情況時間復(fù)雜度指的是特殊情況下的時間復(fù)雜度。

動圖表明的是在數(shù)組 array 中尋找變量 x 第一次出現(xiàn)的位置,若沒有找到,則返回 -1;否則返回位置下標(biāo)。

1intfind(int[]array,intn,intx){2for(inti=0;i

在這里當(dāng)數(shù)組中第一個元素就是要找的 x 時,時間復(fù)雜度是 O(1);而當(dāng)最后一個元素才是 x 時,時間復(fù)雜度則是 O(n)。

最好情況時間復(fù)雜度就是在最理想情況下執(zhí)行代碼的時間復(fù)雜度,它的時間是最短的;最壞情況時間復(fù)雜度就是在最糟糕情況下執(zhí)行代碼的時間復(fù)雜度,它的時間是最長的。

平均情況時間復(fù)雜度

最好、最壞時間復(fù)雜度反應(yīng)的是極端條件下的復(fù)雜度,發(fā)生的概率不大,不能代表平均水平。那么為了更好的表示平均情況下的算法復(fù)雜度,就需要引入平均時間復(fù)雜度。

平均情況時間復(fù)雜度可用代碼在所有可能情況下執(zhí)行次數(shù)的加權(quán)平均值表示。

還是以find函數(shù)為例,從概率的角度看, x 在數(shù)組中每一個位置的可能性是相同的,為 1 / n。那么,那么平均情況時間復(fù)雜度就可以用下面的方式計算:

((1 + 2 + … + n) / n + n) / 2 = (3n + 1) / 4

find函數(shù)的平均時間復(fù)雜度為 O(n)。

均攤復(fù)雜度分析

我們通過一個動態(tài)數(shù)組的push_back操作來理解均攤復(fù)雜度。

1template 2classMyVector{ 3private: 4T*data; 5intsize;//存儲數(shù)組中的元素個數(shù) 6intcapacity;//存儲數(shù)組中可以容納的最大的元素個數(shù) 7//復(fù)雜度為O(n) 8voidresize(intnewCapacity){ 9T*newData=newT[newCapacity];10for(inti=0;i

push_back實現(xiàn)的功能是往數(shù)組的末尾增加一個元素,如果數(shù)組沒有滿,直接往后面插入元素;如果數(shù)組滿了,即size == capacity,則將數(shù)組擴容一倍,然后再插入元素。

例如,數(shù)組長度為 n,則前 n 次調(diào)用push_back復(fù)雜度都為 O(1) 級別;在第 n + 1 次則需要先進行 n 次元素轉(zhuǎn)移操作,然后再進行 1 次插入操作,復(fù)雜度為 O(n)。

因此,平均來看:對于容量為 n 的動態(tài)數(shù)組,前面添加元素需要消耗了 1 * n 的時間,擴容操作消耗 n 時間 ,總共就是 2 * n 的時間,因此均攤時間復(fù)雜度為 O(2n / n) = O(2),也就是 O(1) 級別了。

可以得出一個比較有意思的結(jié)論:一個相對比較耗時的操作,如果能保證它不會每次都被觸發(fā),那么這個相對比較耗時的操作,它所相應(yīng)的時間是可以分?jǐn)偟狡渌牟僮髦衼淼摹?/p>

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 算法
    +關(guān)注

    關(guān)注

    23

    文章

    4709

    瀏覽量

    95326
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4900

    瀏覽量

    70666

原文標(biāo)題:看動畫輕松理解時間復(fù)雜度

文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    DFT算法與FFT算法優(yōu)劣分析

    本文參考銀河電氣官網(wǎng):DFT算法與FFT算法優(yōu)劣分析DFT與它的快速算法FFT相比可能更有優(yōu)勢,而FFT卻存在某些局限性.在只需要求出部分頻點的頻率譜線時DFT的運算時間大為減少,所
    發(fā)表于 05-22 20:43

    想請問下AD9744和LTC1668之間優(yōu)劣對比

    (既然Analog和Linear已經(jīng)合并了,應(yīng)該有專家對這兩款芯片都了解的很透徹吧?) ? 我想生成2MHz以下高精度的正弦信號,現(xiàn)在在AD9744和LTC1668之間糾結(jié),兩者都提供了很不錯的評估
    發(fā)表于 08-13 08:03

    怎樣驗證可部署目標(biāo)硬件與軟件算法模型之間算法性能一致性?

    如何設(shè)計一款合理的電子硬件解決方案,從而實現(xiàn)經(jīng)濟有效的大規(guī)模生產(chǎn)與部署?怎樣驗證可部署目標(biāo)硬件與軟件算法模型之間算法性能一致性?Sys
    發(fā)表于 04-08 06:25

    如何衡量變壓器供電質(zhì)量的好壞

    什么被稱為動作電壓?造成高壓電容器外殼膨脹的原因是什么?如何衡量變壓器供電質(zhì)量的好壞
    發(fā)表于 09-18 07:22

    如何使用幾種公開地國產(chǎn)密碼算法

    國產(chǎn)密碼算法主要有哪幾種?如何使用幾種公開地國產(chǎn)密碼算法
    發(fā)表于 11-09 08:02

    PD算法是如何控制平衡小車的

    平衡小車的原理是什么?PD算法是如何控制平衡小車的?
    發(fā)表于 11-11 06:46

    如何實現(xiàn)基于stm32的PID算法增量式程序

    PID算法可分為哪幾類?PID算法的參數(shù)有哪些?如何實現(xiàn)基于stm32的PID算法增量式程序
    發(fā)表于 12-02 07:48

    基于單片機的pid控制算法該怎樣使用

    pid是什么?pid控制該如何實現(xiàn)?基于單片機的pid控制算法該怎樣使用?
    發(fā)表于 12-21 07:01

    AVR移位算法是如何定義的

    AVR寄存器是如何定義的?AVR移位算法是如何定義的
    發(fā)表于 01-24 07:16

    什么是歸一化算法?怎樣使用歸一化算法

    什么是歸一化算法?怎樣使用歸一化算法?
    發(fā)表于 02-25 06:19

    通過哪些指標(biāo)衡量開關(guān)電源的優(yōu)劣

    通信開關(guān)電源技術(shù)在20世紀(jì)80年代引入我國,如今已廣泛應(yīng)用于通信領(lǐng)域。由于通信開關(guān)電源的性能直接影響著通信系統(tǒng)的可靠性,因此正確判別通信電源的優(yōu)劣也就顯得尤為重要。僅從電源的輸入、輸出特性指標(biāo)來衡量開關(guān)電源的優(yōu)劣,顯然是不夠的,
    的頭像 發(fā)表于 09-21 08:00 ?6604次閱讀

    如何衡量IT運營的成功和指標(biāo)?

    在組織使用云計算基礎(chǔ)設(shè)施為客戶提供新的服務(wù)獲利的時候,應(yīng)該如何衡量IT運營的成功? 通過監(jiān)控設(shè)備上的綠色、黃色或紅色指示燈來衡量IT運營狀態(tài)仍然有用嗎?
    的頭像 發(fā)表于 11-30 11:51 ?2745次閱讀

    選擇耦電容時我們應(yīng)該考慮哪些因素

    電容的安裝方法電容的擺放對于電容的安裝,首先要提到的就是安裝距離。容值最小的電容,有最高的諧振頻率,
    的頭像 發(fā)表于 03-23 17:34 ?2932次閱讀

    怎么判斷支路的個數(shù)

    支路是什么意思?怎么判斷支路的個數(shù)
    的頭像 發(fā)表于 02-02 09:05 ?2.3w次閱讀

    微服務(wù)之間涉及到的數(shù)據(jù)依賴問題應(yīng)該怎么處理?

    微服務(wù),顧名思義,就是將我們程序拆分為最小化單元來提供服務(wù)。在一體化系統(tǒng)中,各個微服務(wù)也是不可能獨立存在的,那么微服務(wù)之間涉及到的數(shù)據(jù)依賴問題,應(yīng)該怎么處理?
    的頭像 發(fā)表于 06-15 10:05 ?997次閱讀
    微服務(wù)<b class='flag-5'>之間</b>涉及到的數(shù)據(jù)依賴問題<b class='flag-5'>應(yīng)該</b>怎么處理<b class='flag-5'>呢</b>?