轉(zhuǎn)載自:https://www.cnblogs.com/huangbw/p/7398418.html
什么是時(shí)間復(fù)雜度
作為一個(gè)處在學(xué)習(xí)之路的渣渣,被一個(gè)時(shí)間復(fù)雜度的題給難倒了,然后我就思考了一下什么是時(shí)間復(fù)雜度。雖然在學(xué)校學(xué)習(xí)了了算法的課程,但是仔細(xì)一想,對(duì)于時(shí)間復(fù)雜度還真是不怎么懂。于是重新學(xué)習(xí),記下自己的一些理解。
1.時(shí)間復(fù)雜度
提到時(shí)間復(fù)雜度,第一時(shí)間想到的是算法,簡(jiǎn)單說(shuō),算法就是你解決問(wèn)題的方法,而你用這個(gè)方法解決這個(gè)問(wèn)題所執(zhí)行的語(yǔ)句次數(shù),稱為語(yǔ)句頻度或者時(shí)間頻度,記為T(n)。
那么問(wèn)題來(lái)了,我們?yōu)槭裁匆脒@些個(gè)概念呢。因?yàn)槲覀兿胍氖菆?zhí)行一個(gè)算法耗費(fèi)的時(shí)間,這個(gè)時(shí)間理論上可以得到,但是,要得到這個(gè)時(shí)間就必須要上機(jī)測(cè)試,但是有這個(gè)必要嗎?我們需要知道的是哪一個(gè)算法需要的時(shí)間多,哪一個(gè)算法需要的時(shí)間少,這樣就可以了。而且,算法的耗時(shí)和語(yǔ)句的執(zhí)行次數(shù)是成正比的,即語(yǔ)句執(zhí)行越多,耗時(shí)越多。這也就是我們引入概念的原因。
在上面提到的時(shí)間頻度T(n)中,n是指算法的規(guī)模,n不斷的變化,T(n)就會(huì)不斷的變化,而這些變化的規(guī)律是怎樣的呢?于是我們引入了時(shí)間復(fù)雜度的概念。
什么是時(shí)間復(fù)雜度,算法中某個(gè)函數(shù)有n次基本操作重復(fù)執(zhí)行,用T(n)表示,現(xià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)),稱O(f(n)) 為算法的漸進(jìn)時(shí)間復(fù)雜度,簡(jiǎn)稱時(shí)間復(fù)雜度。通俗一點(diǎn)講,其實(shí)所謂的時(shí)間復(fù)雜度,就是找了一個(gè)同樣曲線類型的函數(shù)f(n)來(lái)表示這個(gè)算法的在n不斷變大時(shí)的趨勢(shì) 。當(dāng)輸入量n逐漸加大時(shí),時(shí)間復(fù)雜性的極限情形稱為算法的“漸近時(shí)間復(fù)雜性”。
我們用大O表示法表示時(shí)間復(fù)雜性,它是一個(gè)算法的時(shí)間復(fù)雜性。大O表示只是說(shuō)有上界但并不是上確界。
“大O記法”:在這種描述中使用的基本參數(shù)是 n,即問(wèn)題實(shí)例的規(guī)模,把復(fù)雜性或運(yùn)行時(shí)間表達(dá)為n的函數(shù)。這里的“O”表示量級(jí) (order),比如說(shuō)“二分檢索是 O(logn)的”,也就是說(shuō)它需要“通過(guò)logn量級(jí)的步驟去檢索一個(gè)規(guī)模為n的數(shù)組”記法 O ( f(n) )表示當(dāng) n增大時(shí),運(yùn)行時(shí)間至多將以正比于 f(n)的速度增長(zhǎng)。
時(shí)間復(fù)雜度對(duì)于算法進(jìn)行的分析和大致的比較非常有用,但是真正的情況可能會(huì)因?yàn)橐恍┢渌蛩卦斐刹町悺1热缫粋€(gè)低附加代價(jià)的O(n2)算法在n較小的情況下可能比一個(gè)高附加代價(jià)的 O(nlogn)算法運(yùn)行得更快。但是,n越來(lái)越大以后,相比較而言較慢上升函數(shù)的算法會(huì)運(yùn)行的更快。
上面我引用了一些專業(yè)的定義,可能并不是太好理解,下面會(huì)寫一些常出現(xiàn)的算法時(shí)間復(fù)雜度和一些實(shí)例來(lái)解釋一下。
2.簡(jiǎn)單算法的時(shí)間復(fù)雜度舉例
列舉一些簡(jiǎn)單例子的時(shí)間復(fù)雜度。
O(1)的算法是一些運(yùn)算次數(shù)為常數(shù)的算法。例如:
temp=a;a=b;b=temp;
上面語(yǔ)句共三條操作,單條操作的頻度為1,即使他有成千上萬(wàn)條操作,也只是個(gè)較大常數(shù),這一類的時(shí)間復(fù)雜度為O(1)。
O(n)的算法是一些線性算法。例如:
sum=0;
for(i=0;i<n;i++)
sum++;
上面代碼中第一行頻度1,第二行頻度為n,第三行頻度為n,所以f(n)=n+n+1=2n+1。所以時(shí)間復(fù)雜度O(n)。這一類算法中操作次數(shù)和n正比線性增長(zhǎng)。
O(logn) 一個(gè)算法如果能在每個(gè)步驟去掉一半數(shù)據(jù)元素,如二分檢索,通常它就取 O(logn)時(shí)間。舉個(gè)栗子:
int i=1;
while (i<=n)
i=i*2;
上面代碼設(shè)第三行的頻度是f(n), 則:2的f(n)次方<=n;f(n)<=log?n,取最大值f(n)= log?n,所以T(n)=O(log?n ) 。
O(n2)(n的k次方的情況)最常見的就是平時(shí)的對(duì)數(shù)組進(jìn)行排序的各種簡(jiǎn)單算法都是O(n2),例如直接插入排序的算法。
而像矩陣相乘算法運(yùn)算則是O(n3)。
舉個(gè)簡(jiǎn)單栗子:
sum=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
sum++;
第一行頻度1,第二行n,第三行n2,第四行n2,T(n)=2n2+n+1 =O(n2)
O(2的n次方) 比如求具有n個(gè)元素集合的所有子集的算法
O(n!) 比如求具有N個(gè)元素的全排列的算法
時(shí)間復(fù)雜度按n越大算法越復(fù)雜來(lái)排的話:常數(shù)階O(1)、對(duì)數(shù)階O(logn)、線性階O(n)、線性對(duì)數(shù)階O(nlogn)、平方階O(n2)、立方階O(n3)、……k次方階O(n的k次方)、指數(shù)階O(2的n次方)。
既然說(shuō)到了這個(gè)復(fù)雜排序,就必須再多說(shuō)幾句。我們還需要區(qū)分算法最壞情況的行為和期望行為。就比如說(shuō)快速排序,最壞情況運(yùn)行時(shí)間是 O(n2),但期望時(shí)間是O(nlogn)。但是我們只要通過(guò)一些手段,可以避免最壞情況發(fā)生,所以在實(shí)際情況中,精心設(shè)計(jì)的快速排序都能以期望時(shí)間運(yùn)行。
最后再提一下指數(shù)的情況。指數(shù)算法一般來(lái)說(shuō)太復(fù)雜了,所以實(shí)際情況下如果不是迫不得已不要用時(shí)間復(fù)雜度為指數(shù)的算法,除非n特別小。
啰啰嗦嗦寫了很多最基礎(chǔ)的東西,也是想加深一下印象,如果有錯(cuò)誤還請(qǐng)指出。