Algorithm homework 1

1、已知下列遞推式:

\[C(n)= \begin{cases} 1 & , & n = 1 \\ 2C(n/2) + n - 1& , & n \geq 2 \end{cases} \]

請由定理1 導出C(n)的非遞歸表達式並指出其漸進複雜性.算法

定理1:設\(a,c\)爲非負整數,\(b,d,x\)爲非負常數,並對於某個非負整數\(k\), 令\(n=c^k\), 則如下遞推式數組

\[f(n)= \begin{cases} d & , & n=1 \\ af(n/c)+bn^x& , & n\geq2 \end{cases} \]

的解是優化

\[f(n)= \begin{cases} bn^xlog_cn + dn^x & , & n=1 \\ \left( d + \frac{bc^x}{a-c^x} \right)n^{log_ca} - \left( \frac{bc^x}{a-c^x}\right)n^x& , & n\geq2 \end{cases} \]


\(T(n) = C(n) - 1\),則spa

\[T(n)= \begin{cases} 0 & , & n = 1 \\ 2T(n/2) + n & , & n \geq 2 \end{cases} \]

\(T(n)\)知足定理1中遞推式,且\(a = 2, b = 1, c = 2, d = 0, x = 1\), 即有\(2 = 2^1\)
故當\(n = 2^k\)時,\(T(n)\)的解爲設計

\[T(n) = nlog_2n \]

\(C(n)\)的非遞歸表達式爲code

\[C(n) = T(n) + 1 = nlog_2n + 1 \]

因此其漸進複雜性爲\(\Theta(nlog_2n)\)排序

2、因爲Prim算法和Kruskal 算法設計思路的不一樣,致使了其對不一樣問題實例的效率對比關係的不一樣。請簡要論述:

一、如何將兩種算法集成,以適應問題的不一樣實例輸入;

Prim算法基於每一個點, 要遍歷全部的點。
Kruskal算法基於邊, 要遍歷許多邊。
所以能夠在邊比較稀疏的狀況下用Kruskal算法,在邊較稠密的狀況下使用Prim算法.遞歸

二、你如何評價這一集成的意義?

​ 一般實現下Prim是\(O(V^2)\)的時間複雜度,但可使用優先隊列將時間複雜度優化到\(O(Elog_2V)\),而Kruskal使用排序+並查集實現的複雜度爲\(O(Elog_2E)\),二者最優時間複雜度差異僅爲log級別的,且Prim平均狀況下效果會更好。所以這一集成大概只是增長了代碼複雜度,僅用Prim算法的效果可能會更好。隊列

3、分析如下生成排列算法的正確性和時間效率:

HeapPermute(n)
    //實現生成排列的Heap算法
    //輸入:一個正整數n和一個全局數組A[1..n]
    //輸出:A中元素的全排列
    if n = 1
        write A
    else
        for i ← 1 to n do
            HeapPermute(n-1)
            if n is odd
                swap A[1] and A[n]
            else swap A[i] and A[n]

1. 正確性

設 k 爲正整數且 $ k \leq n\(,記\)A[1..n]\(爲\)A=[a_1, a_2, \cdots, a_n]$數學

咱們有如下結論:在執行算法\(HeapPermute(k)\)後, 輸出 A 前 k 位的全排列,後\(n − k\)位不變。(特別地, 當 k = n 時, 輸出的就是 A 的全排列。) 執行算法\(HeapPermute(k)\)先後, 當 k 爲奇數時, A 保持不變;當n爲偶數時, A 的前 k 位循環右移一位。

下面數學概括法證實該結論:
證實

  • (1) 當\(k = 1\)時,算法\(HeapPermute(k)\)輸出\([a_1, a_2, \cdots, a_n]\),與結論相符。
  • (2) 假設當$k = 2j - 1(j \(爲正整數\))\(,且\)k < n \(時,執行\)HeapPermute(k)\(輸出 A 前 k 位的全排列,後\)n − k\(位不變,且A保持不變。則當\)k = 2j\(時,對於\)i = 1, 2, \cdots, 2j$時,分別輸出A的前\(2j-1\)位的全排列,A的後\((n - 2j + 1)\)位不變,程序向下執行到第10行,因爲n爲偶數,則\(swap(a_i,a_{2j})\)。以前全部操做僅改變A數組的前\(2j\)位,而後輸出\(2j - 1\)位,後後\((n - 2j + 1)\)位不變。最後依次將A的第\(1, 2, \cdots, 2j\)位交換到第2m位。所以上述操做獲得了A的前2j位的全排列且前2j位循環右移一位,後\(n-2j\)位不變。與結論相符。
  • (3) 假設當$k = 2j(j \(爲正整數\))\(,且\)k < n\(時,,執行\)HeapPermute(k)\(輸出 A 前 k 位的全排列,後\)n − k\(位不變,且 A 的前 k 位循環右移一位。相似的可獲得當\)k=2j+1$時, A 保持不變。

所以結論得證,執行算法HeapPermute(n)能夠輸出全局數組\(A = [1..n]\)的全排列。

2. 時間效率

考慮交換操做的耗時,有遞推公式以下:

\[T(n)= \begin{cases} 1 & , & n = 1 \\ n\left[T(n - 1) + 1\right] & , & n \geq 2 \end{cases} \]

化簡得\(T(n) = n! + O(n^{n-1})\)

\(T(n)\)的時間複雜度爲\(O(n!) + O(n^{n-1})\)

4、對於求n 個實數構成的數組中最小元素的位置問題,寫出你設計的具備減治思想算法的僞代碼,肯定其時間效率,並與該問題的蠻力算法相比較。

FindMin(n)
    //實現尋找數組中最小元素的位置
    //輸入:一個正正整數n和一個全局數組A[1..n]
    //輸出:A中最小元素m及其位置a
    if n == 1:
        return A[1], 1
    else
        m, a = FindMin(n-1)
    if m <= A[n]:
        return m, a
    else
        return A[n], n

上述減治方法每次將問題的規模約減1,所以時間複雜度爲\(O(n)\),與該問題的蠻力算法時間複雜度相同。

5、請給出約瑟夫斯問題的非遞推公式 J(n),並證實之。其中,n 爲最初總人數,J(n) 爲最後倖存者的最初編號。

約瑟夫問題的非遞推公式爲:

\[J(n) = 1 + 2(n - 2^{\lfloor log_2n \rfloor}), \ n = 1, 2, 3, \cdots \]

\(m = {\lfloor log_2n \rfloor}\)\(l = n - 2^m,\)\(J(n) = 2l+1\)
首先咱們很容易知道該問題的通項公式爲

\[\begin{array}{l} J(2n) = 2J(n) - 1 & , & n 爲偶數 \\ J(2n + 1) = 2J(n) + 1 & ,& n爲奇數 \end{array} \]

下用概括法證實該通項。
證實

  1. \(n = 1\)時,上式顯然成立。
  2. 假設\(n\)是偶數,取\(m_一、l_1\)使得\(n/2=2^{m_{1}}+l_{1}\),且\(0\leq l_{1}<2^{{m_{1}}}\)。這裏\(l_{1}=l/2\)。咱們有\(f(n)=2f(n/2)-1=2((2l_{1})+1)-1=2l+1\),其中第二個等式從概括假設推出。
  3. 假設\(n\)是奇數,則咱們選擇\(l_{1}\)\(m_{1}\),使得\((n-1)/2=2^{{m_{1}}}+l_{1}\),且\(0\leq l_{1}<2^{{m_{1}}}\)。注意\(l_{1}=(l-1)/2\)。咱們有\(f(n)=2f((n-1)/2)+1=2((2l_{1})+1)+1=2l+1\),其中第二個等式從概括假設推出。證畢。

綜上,對全部的天然數n,原結論成立。證畢。

相關文章
相關標籤/搜索