1. 程式人生 > >演算法導論第15章習題答案

演算法導論第15章習題答案

15.2-2

Q:請給出一個遞迴演算法MATRIX-CHAIN-MULTIPLY(A,s,i,j),使之在給出矩陣序列<A1,A2,...,An>,和由MATRIX-CHAIN-ORDER計算出的表s, 以及下標i和j後,能得出一個最有的矩陣鏈乘法。(初始呼叫為MATRIX-CHAIN-MULTIPLY(A,s,1,n))。

A:模仿PRINT-OPTIMAL-PARENS(s,i,j)即可。虛擬碼:

MATRIX-CHAIN-MULTIPLY(A,s,i,j)
{
    if i=j then return Ai;
    else
        return MATRIX
-CHAIN-MULTIPLY(A,s,i,s[i,j])*MATRIX-CHAIN-MULTIPLY(A,s[i,j]+1,j); }

15.4-5

Q:請給出一個O(n^2)時間的演算法,使之能找出一個n個數的序列中最長的單調遞增子序列。

A:這裡給出兩種演算法。

方法1:假設這n個數存在陣列X中,首先將這n個數按單調遞增的順序排序,將排好序的陣列存於Y中。 然後通過計算X和Y的最長公共子序列即可找到答案。

方法2:直接利用動態規劃的思想。設f(i)為以第i個數結尾的最長單調遞增子序列的長度, 則f(i)=max(f(k)+1, 其中k<i且X[k]<X[i]),如果在1到i-1內找不到符合條件的k,那麼f(i)就只能等於1了。 為了方便最後構造最長子序列,還需要另一個數組pre[i]儲存以第i個數結尾的最長遞增子序列的倒數第2個數。 虛擬碼:

LIS-Length(X)
{
    max = 0;
    max_i = 0;
    f[1..n] = 1;
    pre[1..n] = -1;

    for i = 1 to n do
    {
        for k = 1 to i-1 do
            if X[k]<X[i] and f[k]+1 > f[i] then
            {
                f[i] = f[k] + 1;
                pre[i] = k;
            }
    }

    for i = 1
to n do if f[i] > max then max = f[i]; max_i = i return max; } LIS-print(i) { if pre[i] != -1 LIS-print(pre[i]); print i; }

15.4-6

Q:請給出一個O(nlgn)時間的演算法,使之能找出一個n個數的序列中最長的單調遞增子序列。 (提示:觀察長度為i的一個候選因子序列的最後一個元素,它至少與長度為i-1的一個候選子序列的最後一個元素一樣大。通過把候選子序列與輸入序列相連線來維護它們)。

A:這個提示看了好幾遍也沒有看懂說的是什麼意思,大概是翻譯的問題吧。總之需要將演算法改進到O(nlgn)的複雜度。 自己想不到好的辦法,百度了一下,想法還是挺巧妙的,用一個數組D[len]記錄len長的遞增子序列的最小末尾元素。 只需要從1到n一遍掃描中間加上二分查詢,可以得到O(nlgn)的演算法。這裡不詳細討論,附上一個連線: