演算法的複雜度 時間複雜度與空間複雜度

2021-08-21 02:23:30 字數 4148 閱讀 5294

通常,對於乙個給定的演算法,我們要做 兩項分析。第一是從數學上證明演算法的正確性,這一步主要用到形式化證明的方法及相關推理模式,如迴圈不變式、數學歸納法等。而在證明演算法是正確的基礎上,第二步就是分析演算法的時間複雜度。演算法的時間複雜度反映了程式執行時間隨輸入規模增長而增長的量級,在很大程度上能很好反映出演算法的優劣與否。因此,作為程式設計師,掌握基本的演算法時間複雜度分析方法是很有必要的。

演算法執行時間需通過依據該演算法編制的程式在計算機上執行時所消耗的時間來度量。而度量乙個程式的執行時間通常有兩種方法。

一、事後統計的方法

這種方法可行,但不是乙個好的方法。該方法有兩個缺陷:一是要想對設計的演算法的執行效能進行評測,必須先依據演算法編制相應的程式並實際執行;二是所得時間的統計量依賴於計算機的硬體、軟體等環境因素,有時容易掩蓋演算法本身的優勢。

二、事前分析估算的方法

因事後統計方法更多的依賴於計算機的硬體、軟體等環境因素,有時容易掩蓋演算法本身的優劣。因此人們常常採用事前分析估算的方法。

在編寫程式前,依據統計方法對演算法進行估算。乙個用高階語言編寫的程式在計算機上執行時所消耗的時間取決於下列因素:

(1). 演算法採用的策略、方法

(2). 編譯產生的**質量

(3). 問題的輸入規模

(4). 機器執行指令的速度。

乙個演算法是由控制結構(順序、分支和迴圈3種)和原操作(指固有資料型別的操作)構成的,則演算法時間取決於兩者的綜合效果。為了便於比較同乙個問題的不同演算法,通常的做法是,從演算法中選取一種對於所研究的問題(或演算法型別)來說是基本操作的原操作,以該基本操作的重複執行的次數作為演算法的時間量度。

演算法分析的分類:

演算法存在最好、平均和最壞情況:

例如:在乙個長度為n的線性表中搜尋乙個資料x

在實際中通常關注的是演算法的最壞運**況,即:任意輸入規模演算法的最長執行時間,理由如下:

乙個演算法的最壞情況的執行時間是在任意輸入下的執行時間上界

對於某些演算法,最壞演算法情況較為頻繁

大體看,平均情況與最壞情況一樣差

時間複雜度之大o漸進表示法

n稱為問題的規模,當n不斷變化時,時間頻度t(n)也會不斷變化。但有時我們想知道它變化時呈現什麼規律。為此,我們引入時間複雜度概念。 一般情況下,演算法中基本操作重複執行的次數是問題規模n的某個函式,用t(n)表示,若有某個輔助函式f(n),使得當n趨近於無窮大時,t(n)/f(n)的極限值為不等於零的常數,則稱f(n)是t(n)的同數量級函式。記作t(n)=o(f(n)),稱o(f(n)) 為演算法的漸進時間複雜度,簡稱時間複雜度。

求解演算法的時間複雜度的具體步驟是:

⑴ 找出演算法中的基本語句;

演算法中執行次數最多的那條語句就是基本語句,通常是最內層迴圈的迴圈體。

⑵ 計算基本語句的執行次數的數量級;

只需計算基本語句執行次數的數量級,這就意味著只要保證基本語句執行次數的函式中的最高次冪正確即可,可以忽略所有低次冪和最高次冪的係數。這樣能夠簡化演算法分析,並且使注意力集中在最重要的一點上:增長率。

⑶ 用大ο記號表示演算法的時間效能。

將基本語句執行次數的數量級放入大ο記號中。

如果演算法中包含巢狀的迴圈,則基本語句通常是最內層的迴圈體,如果演算法中包含並列的迴圈,則將並列迴圈的時間複雜度相加。例如:

for (i=1; i

<=n; i++)

x++;

for (i=1; i

<=n; i++)

for (j=1; j

<=n; j++)

x++;

第乙個for迴圈的時間複雜度為ο(n),第二個for迴圈的時間複雜度為ο(n2),則整個演算法的時間複雜度為ο(n+n2)=ο(n2)。

在計算演算法時間複雜度時有以下幾個簡單的程式分析法則:

(1).對於一些簡單的輸入輸出語句或賦值語句,近似認為需要o(1)時間

(2).對於順序結構,需要依次執行一系列語句所用的時間可採用大o下」求和法則」

求和法則:是指若演算法的2個部分時間複雜度分別為 t1(n)=o(f(n))和 t2(n)=o(g(n)),則 t1(n)+t2(n)=o(max(f(n), g(n)))

特別地,若t1(m)=o(f(m)), t2(n)=o(g(n)),則 t1(m)+t2(n)=o(f(m) + g(n))

(3).對於選擇結構,如if語句,它的主要時間耗費是在執行then字句或else字句所用的時間,需注意的是檢驗條件也需要o(1)時間

(4).對於迴圈結構,迴圈語句的執行時間主要體現在多次迭代中執行迴圈體以及檢驗迴圈條件的時間耗費,一般可用大o下」乘法法則」

乘法法則: 是指若演算法的2個部分時間複雜度分別為 t1(n)=o(f(n))和 t2(n)=o(g(n)),則 t1*t2=o(f(n)*g(n))

(5).對於複雜的演算法,可以將它分成幾個容易估算的部分,然後利用求和法則和乘法法則技術整個演算法的時間複雜度

另外還有以下2個運算法則:(1) 若g(n)=o(f(n)),則o(f(n))+ o(g(n))= o(f(n));(2) o(cf(n)) = o(f(n)),其中c是乙個正常數

簡單總結:

對於一般演算法時間複雜度計算方法:

-用常數1取代執行時間裡的所有加法常數

- 在修改的執行次數函式中,只保留最高端項

- 如果最高端項存在且不為1,則去掉最高次項的係數

對於遞迴演算法時間複雜度:

遞迴演算法時間複雜度 = 遞迴總次數 * 每次遞迴次數

常見的演算法時間複雜度由小到大依次為:ο(1)<ο(log2n)<ο(n)<ο(nlog2n)<ο(n2)<ο(n3)<…<ο(2n)<ο(n!)

演算法複雜度常用術語

常見的時間複雜度進行示例說明:

(1)、o(1)

temp=i; i=j; j=temp;
以上三條單個語句的頻度均為1,該程式段的執行時間是乙個與問題規模n無關的常數。演算法的時間複雜度為常數階,記作t(n)=o(1)。注意:如果演算法的執行時間不隨著問題規模n的增加而增長,即使演算法中有上千條語句,其執行時間也不過是乙個較大的常數。此類演算法的時間複雜度是o(1)。

(2)、o(n2)

for (int n=0;n<10,n++)

n++;

for (i=1; i

<=n; i++)

x++;

for (i=1; i

<=n; i++)

for (j=1; j

<=n; j++)

x++;

因為o(n2+10)=n2;(去掉常數項得到),所以t(n)= =o(n2)

(3)、o(n*m)

void test(int m,int n)

{

int icount=0;

for(inti=0;i<2*m;i++)

{for(int j=0;jt(n)= =o(2*m*n)–>t(n)= =o(m*n)

(4)、o(n+m)

int icount=0;

for (int n=0;nfor (int i=0; it(n)=t1(m)+t2(n)=o(m+n))

(5)、求1+2+3+…+n之和

t(n)=o(遞迴總次數(n)*每次遞迴次數(1))=o(n)

(6)、求n的階乘

這是乙個遞迴程,可以看出每遞迴一次n的規模小一,所是結果是線性的:t(n)=o(n)

空間複雜度

乙個演算法的空間複雜度(space complexity)s(n)定義為該演算法所耗費的儲存空間,它也是問題規模n的函式。漸近空間複雜度也常常簡稱為空間複雜度。

空間複雜度(space complexity)是對乙個演算法在執行過程中臨時占用儲存空間大小的量度。乙個演算法在計算機儲存器上所占用的儲存空間,包括儲存演算法本身所占用的儲存空間,演算法的輸入輸出資料所占用的儲存空間和演算法在執行過程中臨時占用的儲存空間這三個方面。

一般情況下用o漸進表示法表示空間複雜度。

對於遞迴演算法的空間複雜度 = 遞迴深度 * 每次遞迴次數

演算法時間複雜度空間複雜度

演算法 是解決某一類問題的通法,即一系列清晰無歧義的計算指令。每個演算法只能解決具有特定特徵的一類問題,但乙個問題可由多個演算法解決。乙個演算法應該有以下五個方面的特性 比較演算法的優劣我們從兩個維度去進行考量 時間 空間 時間複雜度,空間複雜度 找出基本語句 演算法中執行次數最多的那條語句就是基本...

演算法 時間複雜度 空間複雜度

1 if i 1 2 a 1 result 3 4 result n 2 result 1000 1000 3 array.push a array.pop 4 map.set 1,1 map.get 1,1 在計算複雜度的時候,o 1 一般會被忽略。1 for let i 0 i n i 2 wh...

演算法複雜度 時間複雜度和空間複雜度

1 時間複雜度 1 時間頻度 乙個演算法執行所耗費的時間,從理論上是不能算出來的,必須上機執行測試才能知道。但我們不可能也沒有必要對每個演算法都上機測試,只需知道哪個演算法花費的時間多,哪個演算法花費的時間少就可以了。並且乙個演算法花費的時間與演算法中語句的執行次數成正比例,哪個演算法中語句執行次數...