乙個演算法是由控制結構(順序、分支和迴圈3種)和原操作(指固有資料型別的操作)構成的,則演算法時間取決於兩者的綜合效果。為了便於比較同乙個問題的不同演算法,通常的做法是,從演算法中選取一種對於所研究的問題(或演算法型別)來說是基本操作的原操作,以該基本操作的重複執行的次數作為演算法的時間量度。
1、時間複雜度
(1)時間頻度乙個演算法執行所耗費的時間,從理論上是不能算出來的,必須上機執行測試才能知道。但我們不可能也沒有必要對每個演算法都上機測試,只需知道哪個演算法花費的時間多,哪個演算法花費的時間少就可以了。並且乙個演算法花費的時間與演算法中語句的執行次數成正比例,哪個演算法中語句執行次數多,它花費時間就多。乙個演算法中的語句執行次數稱為語句頻度或時間頻度。記為t(n)。
(2)時間複雜度在剛才提到的時間頻度中,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))為演算法的漸進時間複雜度,簡稱時間複雜度。
另外,上面公式中用到的 landau符號其實是由德國數論學家保羅·**曼(paul bachmann)在其2023年的著作《解析數論》首先引入,由另一位德國數論學家艾德蒙·朗道(edmund landau)推廣。landau符號的作用在於用簡單的函式來描述複雜函式行為,給出乙個上或下(確)界。在計算演算法複雜度時一般只用到大o符號,landau符號體系中的小o符號、θ符號等等比較不常用。這裡的o,最初是用大寫希臘字母,但現在都用大寫英語字母o;小o符號也是用小寫英語字母o,θ符號則維持大寫希臘字母θ。
t (n) = ο(f (n))表示存在乙個常數c,使得在當n趨於正無窮時總有 t (n) ≤ c * f(n)。簡單來說,就是t(n)在n趨於正無窮時最大也就跟f(n)差不多大。也就是說當n趨於正無窮時t (n)的上界是c * f(n)。其雖然對f(n)沒有規定,但是一般都是取盡可能簡單的函式。例如,o(2n
2+n +1) = o (3n
2+n+3) = o (7n
2 + n) =o ( n
2 ),一般都只用o(n
2)表示就可以了。注意到大o符號裡隱藏著乙個常數c,所以f(n)裡一般不加係數。如果把t(n)當做一棵樹,那麼o(f(n))所表達的就是樹幹,只關心其中的主幹,其他的細枝末節全都拋棄不管。
在各種不同演算法中,若演算法中語句執行次數為乙個常數,則時間複雜度為o(1),另外,在時間頻度不相同時,時間複雜度有可能相同,如t(n)=n
2+3n+4與t(n)=4n
2+2n+1它們的頻度不同,但時間複雜度相同,都為o(n
2)。 按數量級遞增排列,常見的時間複雜度有:常數階o(1),對數階o(log2n),線性階o(n),線性對數階o(nlog2n),平方階o(n
2),立方階o(n
3),..., k次方階o(n
k),指數階o(2
n)。隨著問題規模n的不斷增大,上述時間複雜度不斷增大,演算法的執行效率越低。
從圖中可見,我們應該盡可能選用多項式階o(n
k)的演算法,而不希望用指數階的演算法。
常見的演算法時間複雜度由小到大依次為:ο(1)<ο(log2n)<ο(n)<ο(nlog2n)<ο(n
2)<ο(n
3)<…<ο(2
n)<ο(n!)
一般情況下,對乙個問題(或一類演算法)只需選擇一種基本操作來討論演算法的時間複雜度即可,有時也需要同時考慮幾種基本操作,甚至可以對不同的操作賦予不同的權值,以反映執行不同操作所需的相對時間,這種做法便於綜合比較解決同一問題的兩種完全不同的演算法。
(3)求解演算法的時間複雜度的具體步驟是:
⑴ 找出演算法中的基本語句;
演算法中執行次數最多的那條語句就是基本語句,通常是最內層迴圈的迴圈體。
⑵ 計算基本語句的執行次數的數量級;
只需計算基本語句執行次數的數量級,這就意味著只要保證基本語句執行次數的函式中的最高次冪正確即可,可以忽略所有低次冪和最高次冪的係數。這樣能夠簡化演算法分析,並且使注意力集中在最重要的一點上:增長率。
⑶ 用大ο記號表示演算法的時間效能。
將基本語句執行次數的數量級放入大ο記號中。
如果演算法中包含巢狀的迴圈,則基本語句通常是最內層的迴圈體,如果演算法中包含並列的迴圈,則將並列迴圈的時間複雜度相加。例如:
第乙個for迴圈的時間複雜度為ο(n),第二個for迴圈的時間複雜度為ο(n
2),則整個演算法的時間複雜度為ο(n+n
2)=ο(n
2)。ο(1)表示基本語句的執行次數是乙個常數,一般來說,只要演算法中不存在迴圈語句,其時間複雜度就是ο(1)。其中ο(log2n)、ο(n)、 ο(nlog2n)、ο(n
2)和ο(n
3)稱為多項式時間,而ο(2
n)和ο(n!)稱為指數時間。計算機科學家普遍認為前者(即多項式時間複雜度的演算法)是有效演算法,把這類問題稱為p(polynomial,多項式)類問題,而把後者(即指數時間複雜度的演算法)稱為np(non-deterministic polynomial, 非確定多項式)問題。
一般來說多項式級的複雜度是可以接受的,很多問題都有多項式級的解——也就是說,這樣的問題,對於乙個規模是n的輸入,在n^k的時間內得到結果,稱為p問題。有些問題要複雜些,沒有多項式時間的解,但是可以在多項式時間裡驗證某個猜測是不是正確。比如問4294967297是不是質數?如果要直接入手的話,那麼要把小於4294967297的平方根的所有素數都拿出來,看看能不能整除。還好尤拉告訴我們,這個數等於641和6700417的乘積,不是素數,很好驗證的,順便麻煩轉告費馬他的猜想不成立。大數分解、hamilton迴路之類的問題,都是可以多項式時間內驗證乙個「解」是否正確,這類問題叫做np問題。
(4)在計算演算法時間複雜度時有以下幾個簡單的程式分析法則:
(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是乙個正常數
(5)下面分別對幾個常見的時間複雜度進行示例說明:
(1)、o(1)
temp=i; i=j; j=temp;
以上三條單個語句的頻度均為1,該程式段的執行時間是乙個與問題規模n無關的常數。演算法的時間複雜度為常數階,記作t(n)=o(1)。注意:如果演算法的執行時間不隨著問題規模n的增加而增長,即使演算法中有上千條語句,其執行時間也不過是乙個較大的常數。此類演算法的時間複雜度是o(1)。
dfs時間複雜度 時間複雜度 空間複雜度
時間複雜度的數學證明方法相對比較複雜,通常在工程實際中,會分析就好。注意 只看最高複雜度的運算 int for for for for int遞迴如何分析時間複雜度?常數係數可以忽略,在分析時不用考慮,只要說以上術語即可。主定理 master throrem 上述第四種是歸併排序,所有排序演算法,最...
時間複雜度 空間複雜度
時間複雜度 在電腦科學中,演算法的時間複雜度是乙個函式,它定性描述了該演算法的執行時間。這是乙個關於代表演算法輸入值的字串 的長度的函式。時間複雜度常用大o符號 表述,不包括這個函式的低階項和首項係數。計算時間複雜度的方法 1 只保留高階項,低階項直接丟棄 2 係數不要 3 執行次數是常數是為o 1...
時間複雜度 空間複雜度
演算法複雜度分為時間複雜度和空間複雜度。其作用 時間複雜度是指執行演算法所需要的計算工作量 而空間複雜度是指執行這個演算法所需要的記憶體空間。一 時間複雜度 時間頻度 乙個演算法執行所耗費的時間,從理論上是不能算出來的,必須上機執行測試才能知道。但我們不可能也沒有必要對每個演算法都上機測試,只需知道...