1. 程式人生 > >遞迴演算法的複雜度分析

遞迴演算法的複雜度分析

 首先介紹3種表示複雜度的符號:

  1. Tight 上下界,f = tight(g)表示當輸入大於某個整數時,存在常數c1和c2,使得 c1*g < f < c2*g ;
  2. Lower 下界, f = Lower(g)表示當n足夠大的時候,存在c,使得 f<g *c;
  3. Upper上界, f = upper(g) 表示你足夠大的時候,存在c使得 f> g * c;

演算法複雜度分析就是求g的過程。通常來講,演算法的上界複雜度才有意義,即第二種,它表現了演算法的優劣。

遞迴演算法的複雜度求法不同於普通的演算法,以歸併排序為例,它的複雜度可以表示如下:

T(n) = 2 * T(n/2) +Lower(n)

它表示規模為n的演算法所需時間是規模為n/2的兩倍加上對整個陣列進行掃描的時間。

最簡單的求解演算法是替換法,它由兩個步驟組成:

  1. 猜測複雜度函式;
  2. 用猜測的函式替換遞迴表示式中的複雜度函式,並推導等式是否成立;

以上面的遞迴表示式為例,我們猜測複雜度為g=nlg(n),這也意味著當n最夠大的時候f< n*lg(n)*c

現在用這個表示式替換 T(n/2),並推匯出T(n)也符合這個猜測:

T(n)  = 2 * T(n/2) +Lower(n)

       <= 2 * n/2 *lg(n/2)*c+c2 * n

       = n *(lg(n) -1) *c + c2*n

      = n * lg(n)* c + (c2-c)* n

    < c * n * lg(n)

最後一步假設c2<c。由於這個兩個常數都是自己選定的,所以可以做到這一點。

在使用替換方法時,最難的是猜測出表示式的形式 g。同時要注意到g中的c是常數,不能隨著n而變化。有時可以通過變數替換的方法,將近似的表示式變換成熟悉的表示式。

使用遞迴樹的方法可以較容易的猜測出表示式的形式。遞迴樹的思想是,輸入為n的複雜度是幾個較小輸入的複雜度的總和,這樣一層一層的劃分下去,會形成一個樹。在樹的每一層會增加複雜度,最後樹的葉子節點是簡單的操作,我們可以認為他的複雜度為常數c。這樣我們只需要求的葉子節點的數量,以及樹的層數,就可以計算出整個演算法的複雜度。

以上面的歸併排序演算法為例,假設有n個節點,那麼每個父親兩個孩子,所以有lg(n)層,每層複雜度為n,最後葉節點是n個。所以複雜度是n * lg(n) * c + n, 由於n的次數較低,所以略去。

利用遞迴樹可以得到一個遞迴複雜度的通解,如下所示:

0=========(x / V)----+++++(x)+++++-------(x*V)^^^^^^^^^

首先給所有的遞迴複雜度一個統一的定義:

T(n)=aT(n/b)+f(n), a>1,b>1

那麼x表示n的lg(a)/lg(b)次方。

V是n的一個未知的正數次方,任何正數都可以,0.1,0.0001,1,100。

上面那一排表示f(n)可能的複雜度,可以看到從左到右,逐漸增大。隨著f(n)的複雜度不同,演算法的複雜度也不一樣。

  1. 在====區域,演算法複雜度由x/v確定,T(n)=tight(x)
  2. 在++++區域,複雜度為 T(n)=Tight(X*lg(n))
  3. 在^^^^區域,複雜度由f(n)確定,T(n)=Tight(f(n))

最後一個有一個額外的限制,不過我還不明白為什麼需要這個限制,這個限制是:a* f(n/b)<=c*f(n)其中c是小於1的常數。

推理很簡單,設f(n)=n的y次方。

那麼進入第三種情況說明,f(n)>x,也就是說y大於lg(a)/lg(b),也就說明a<b的y次方。

再回到a*f(n/b)<c f(n)上來,如果要滿足題意,只需要則a* (n/b)的y次方<c*n的次方,那麼只需要a<c*b的y次方。

由於a,b,y都是常數,必然可以求得一個c使得上面的等式成立。

最後是一個思考題,a[1...n]存放0到n共n+1個整數,只能進行一個操作"讀取第i個元素的第j個bit",如何在Lower(n)的複雜度內找到丟失那個數。

我想到的方法是我們可以知道在0到31個bit上,所有整數共有多少個1是確定的。那麼對n個數掃描32遍,肯定能發現在某幾個位置上1丟失了,把這些1組合起來,就是我們丟失的陣列。

不知道更好的解法是什麼。

相關推薦

演算法複雜分析-主方法及

主方法        主方法是一個演算法複雜度分析的一個很好的方法,但是隻能用於特定的遞迴上,適合的遞迴形式為: T(n) = a*T(n/b)+f(n)        其中,a >=1 ; b >1 ; f(n) : 非遞迴函式,f(n)漸進趨正,漸

演算法與資料結構】演算法複雜分析

一、什麼是複雜度分析? 1.資料結構和演算法解決是“如何讓計算機更快時間、更省空間的解決問題”。 2.因此需從執行時間和佔用空間兩個維度來評估資料結構和演算法的效能。 3.分別用時間複雜度和空間複雜度兩個概念來描述效能問題,二者統稱為複雜度。 4.複雜度描述的是演算法執行時間(或佔用空間)與資料

13、【演算法演算法複雜分析

一、演算法的時間複雜度分析 1、時間複雜度的定義     在進行演算法分析時,演算法中基本操作語句重複執行的次數是問題規模n的某個函式,用T(n)表示,若有某個輔助函式f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函式,

演算法複雜分析(上):分析演算法執行時,時間資源及空間資源的消耗

前言 演算法複雜度是指演算法在編寫成可執行程式後,執行時所需要的資源,資源包括時間資源和記憶體資源。 複雜度也叫漸進複雜度,包括時間複雜度和空間複雜度,用來粗略分析執行效率與資料規模之間的增長趨勢關係,越高階複雜度的演算法,執行效率越低。 複雜度分析是資料結構與演算法的核心精髓,指在不依賴硬體、宿主環境

LeetCode 50 Pow(x, n) —— 可分治問題用降低複雜

起初拿到這個問題,感覺這絲毫不像是中等難度題,一個迴圈即可解決問題。大鍵盤一揮寫出如下程式碼: class Solution { public: double myPow(double x, int n) { double sum; int t;

演算法複雜分析(時間複雜,空間複雜)

前幾天被問到虛擬DOM的時間複雜度,一臉蒙圈,什麼是時間複雜度,我可能大學的資料結構課都在睡覺吧,今天來看看巨人的肩膀。 為什麼要進行演算法分析? 預測演算法所需的資源: 計算時間(CPU消耗) 記憶體空間(RAM消耗) 通訊時間(頻寬消耗) 預測演算法的執行時間: 在給定輸入規

04-演算法複雜分析(下):最好、最壞、平均、均攤時間複雜

上一節,我們講了複雜度的大 O 表示法和幾個分析技巧,還舉了一些常見覆雜度分析的例子,比如 O(1)、O(logn)、O(n)、O(nlogn) 複雜度分析。掌握了這些內容,對於複雜度分析這個知識點,你已經可以到及格線了。但是,我想你肯定不會滿足於此。 今天我會

演算法複雜分析中的符號(Θ、Ο、ο、Ω、ω)簡介

Θ,讀音:theta、西塔;既是上界也是下界(tight),等於的意思。 Ο,讀音:big-oh、歐米可榮(大寫);表示上界(tightness unknown),小於等於的意思。 ο,讀音:small-oh、歐米可榮(小寫);表示上界(not tight),小於的意思。

3.4.3演算法的效率分析

1.時間複雜度的分析 在演算法分析中,當一個演算法中包含遞迴呼叫時,其時間複雜度的分析可以轉化為一個遞迴方程求解。也就是數學上求漸進解得問題,而遞迴方唱的形式多種多樣,其求解方法也不盡相同。迭代法是求解遞迴方程的一種常用方法,其基本步驟是迭代地展開遞迴方程的右端,使之成為一個非遞迴的

演算法-複雜分析:如何分析、統計演算法的執行效率和資源消耗?

整理自極客時間-資料結構與演算法之美。購買地址(有音訊、更完整): 只要講到資料結構與演算法,就一定離不開時間、空間複雜度分析。而且 我個人認為複雜度分析是真個演算法的精髓,只要掌握了它,資料結構和演算法的內容基本上就掌握了一半。 1.為什麼需要複雜度分析? 你可能

資料結構與演算法隨筆之------演算法複雜分析

一.演算法 1.演算法定義 2.什麼是好的演算法        常見的演算法時間複雜度由小到大依次為:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!) 此外,當你遇到一個Ο(n2)的演算法

學好資料結構和演算法 —— 複雜分析

複雜度也稱為漸進複雜度,包括漸進時間複雜度和漸進空間複雜度,描述演算法隨資料規模變化而逐漸變化的趨勢。複雜度分析是評估演算法好壞的基礎理論方法,所以掌握好複雜度分析方法是很有必要的。 時間複雜度   首先,學習資料結構是為了解決“快”和“省”的問題,那麼如何去評估演算法的速度快和省空間呢?這就需要掌握時間

c++ 演算法複雜分析

1.案例比較 2.複雜度的漸進表示法 3. 函式時間比較和影象 4.複雜度判斷小竅門 加減法不考慮,只考慮乘除 舉例子: // 技巧,先找執行次數,然後用t*(每次的複雜度) //O(1)複雜度 int aFunc(void) {

演算法複雜分析——數學角度

平均複雜度、漸進確界 摘要      本文論述了在演算法分析領域一個重要問題——時間複雜度分析的基礎內容。本文將首先明確時間複雜度的意義,而後以形式化方式論述其在數學上的定義及相關推導。從而幫助大家從本質上認清這個概念。前言      通常,對於一個給定的演算法,我們要做

堆排序中--建堆的演算法複雜分析O(n)

程式碼: [cpp] view plaincopyprint? template<class T> inlinevoid MaxHeap<T>::make_heap(vector<T> & v) {  if (heap_

的實質以及時間複雜的計算

說到遞迴,總會提到這麼幾個問題: 遞迴和迭代的區別是什麼? 答:迭代式調別人,而遞迴是調自己 遞迴能不能改為迭代? 答:可以 那麼遞迴的實質是什麼?今天就說一下遞迴的實質 1.遞迴的實質:壓

歐幾里德演算法複雜分析

歐幾里得演算法 function Euclid(a; b) 1: if b = 0 then 2: return a; 3: end if 4: return Euclid(b; a mod b)

跳臺階問題|斐波那契複雜問題|整數劃分問題

struct matrix_2by2 { matrix_2by2(long long a_00 = 0, long long a_01 = 0, long long a_10 = 0, long long a_11 = 0) :a00(a_00),a01(a_01),a10(a_10),a11(a_11)

演算法複雜分析

一 、時間複雜度    演算法複雜度分為時間複雜度和空間複雜度。其作用: 時間複雜度是度量演算法執行的時間長短;而空間複雜度是度量演算法所需儲存空間的大小。任何演算法執行所需要的時間幾乎總是取決於他所處理的資料量,在這裡我們主要說時間複雜度。對於一個給定計算機的演算法

資料結構::時間複雜的計算

開篇前言:為什麼寫這篇文章?筆者目前在學習各種各樣的演算法,在這個過程中,頻繁地碰到到遞迴思想和分治思想,驚訝於這兩種的思想的偉大與奇妙的同時,經常要面對的一個問題就是,對於一個給定的遞迴演算法或者用分治思想縮小問題規模的演算法,如何求解這個演算法的時間複雜度呢?在goo