演算法的時間複雜度

2021-09-08 14:06:43 字數 3440 閱讀 8986

時間頻度:

乙個演算法執行所耗費的時間,從理論上是不能算出來的,必須上機執行測試才能知道。

但我們不可能也沒有必要對每個演算法都上機測試。

乙個演算法花費的時間與演算法中語句的執行次數成正比例,哪個演算法中語句執行次數多,它花費時間就多。

乙個演算法中的語句執行次數稱為語句頻度或時間頻度,表示為t(n),n表示問題的規模

時間複雜度

但有時我們想知道它變化時呈現什麼規律,想知道問題的規模,而不是具體的次數,此時引入時間複雜度。

一般情況下,演算法中基本操作重複執行的次數是問題規模n的某個函式,用t(n)表示,

若有某個輔助函式f(n),使得當n趨近於無窮大時,t(n)/f(n)的極限值為不等於零的常數,則稱f(n)是t(n)的同數量級函式。

記作t(n)=o(f(n)),稱o(f(n)) 為演算法的漸進時間複雜度,簡稱時間複雜度。

t(n)=o(f(n))

或者說:時間複雜度就是時間頻度去掉低階項和首項常數。

注意:時間頻度與時間複雜度是不同的,時間頻度不同但時間複雜度可能相同。        

比如:某兩個演算法的時間頻度是 t(n) = 100000n2+10n+6   t(n) = n2       t(n) = n3

但是時間複雜度都是 t(n) = o(n2)

最壞時間複雜度和平均時間複雜度        

最壞情況下的時間複雜度稱最壞時間複雜度。一般不特別說明,討論的時間複雜度均是最壞情況下的時間複雜度。

這樣做的原因是:最壞情況下的時間複雜度是演算法在任何輸入例項上執行時間的上界,這就保證了演算法的執行時間不會比任何更長。

在最壞情況下的時間複雜度為t(n)=o(n),它表示對於任何輸入例項,該演算法的執行時間不可能大於o(n)。

平均時間複雜度是指所有可能的輸入例項均以等概率出現的情況下,演算法的期望執行時間。鑑於平均複雜度

第一,難計算

第二,有很多演算法的平均情況和最差情況的複雜度是一樣的。

所以一般討論最壞時間複雜度

比如 我要求你在字典里查同乙個字,告訴我這個字在字典的那一頁。

如果一頁一頁的翻,你需要多少時間呢?

最優的情況就是這個字在第一頁,

最壞的情況就是這個字是 整本字典的最後乙個字。

所以即使我故意為難你,你也不會花費比找整本字典最後乙個字還長的時間。

當然,此時聰明的你就會想用部首、筆畫等去查,才不要傻乎乎的一頁一頁翻,

此時的你就會擇優選擇,因為此時你最壞得情況就是我給你部首筆畫最多、除部首外筆畫最多的乙個超級複雜的乙個字,但顯然比翻整本字典快得多。

為了進一步說明演算法的時間複雜度,我們定義 ο、ω、θ符號。

ο(歐公尺可榮)符號給出了演算法時間複雜度的上界(最壞情況  <=),比如t(n) =o(n2)

ω(歐公尺伽)符號給出了時間複雜度的下界(最好情況 >=),比如t(n) =ω(n2)

而θ(西塔)給出了演算法時間複雜度的精確階(最好和最壞是同乙個階  =),比如t(n) =θ(n2)

時間複雜度計算

根本沒有必要計算時間頻度,即使計算處理還要忽略常量、低次冪和最高次冪的係數,所以可以採用如下簡單方法:

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

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

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

只需計算基本語句執行次數的數量級,這就意味著只要保證基本語句執行次數的函式中的最高次冪正確即可,

可以忽略所有低次冪和最高次冪的係數。這樣能夠簡化演算法分析,並且使注意力集中在最重要的一點上:增長率。

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

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

時間複雜度舉例        

乙個簡單語句的時間複雜度為o(1)。

int count=0;

100個簡單語句的時間複雜度也為o(1)。(100是常數,不是趨向無窮大的n)

int count=0;

乙個迴圈的時間複雜度為o(n)。

int n=8, count=0;

for (int i=1; i<=n; i++)

count++;

t(n)=o(n)

時間複雜度為o(log2 n)的迴圈語句。

int n=8, count=0;

for (int i=1; i<=n; i*=2)

count++;

時間複雜度為o(n2)的二重迴圈。

int n=8, count=0;

for (int i=1; i<=n; i++)

for (int j=1; j<=n; j++)

count++;

時間複雜度為o(nlog2n)的二重迴圈。

int n=8, count=0;

for (int i=1; i<=n; i*=2)

for (int j=1; j<=n; j++)

count++;

*************************==

for(int j=1; j<=n; j*=2)

這個迴圈最終執行的次數假設為x,則x次的時候j=2^x 。

當j>n時停止執行,於是2^x>n ,則可以認為該迴圈一共執行了log2(n)次。

所以該迴圈的時間複雜度為o(log2(n)),簡記為o(log n) ,忽略掉2的底數。

方法:1、首先,看外迴圈for(i=0;i2、再看內部迴圈,for(j=1;jn===》x=log2(n)。

3、如果把兩個迴圈合在一起看,也就是一共迴圈了n個x次,也就是log2(n)。

*********************************************

時間複雜度為o(n2)的二重迴圈。

int n=8, count=0;

for (int i=1; i<=n; i++)

for (int j=1; j<=i; j++)

count++;

需要複雜些數**算:1+2+3+.....+n=(n+1)*n/2  時間複雜度是 o(n2)

時間複雜度為o(n2)的二重迴圈。

int n=8, count=0;

for (int i=1; i<=n; i++)

for (int j=1; j<=i; j++)

count++;

後面講解查詢和排序演算法時會大量的設計時間複雜度,作為選擇查詢和排序演算法的重要依據

常用的時間複雜度級別

常數階o(1)

對數階o(log2n)

線性階o(n)

線性對數階o(n*log2n)

平方階o(n2)  

立方階o(n3)

...k次方階o(nk)

指數階o(2n)

階乘階o(n!)

上面各種時間複雜度級別,執行效率越來越低。

大家發現對數階o(log2n)和線性階o(n)的效率差異了嗎,當n=10的8次方(1億)時,執行此時乙個是1億次,乙個是8次。

所以編寫演算法時一定要注意時間複雜度的選擇。

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

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

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

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...

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

時間複雜度和空間複雜度是度量演算法效率的常用指標 事後統計,不常用 事前統計影響因素 演算法策略 問題規模 程式語言 質量 機器執行指令的速度 撇開軟硬體的影響,演算法執行工作量的大小只依賴於問題的規模 通常用整數n表示 乙個演算法是由控制結構 順序,分支,迴圈三種 和原操作 指固有資料型別的操作 ...