第二章 2 3節

2021-06-27 00:06:11 字數 3940 閱讀 5944

2.3-1

使用圖2-4作為模型,說明歸併排序再陣列a=<3, 41, 52, 26, 38, 57, 9, 49>

解答:兩個數中間的「-」號為連線符,代表「-」號兩邊的數歸併一起。

① 3   41  52    26  38   57  9   49

② 3 - 41  26 - 52  38 - 57  9 - 49

③ 3 - 26 - 41 - 52  9 - 38 - 49 - 57

④ 3 - 9 - 26 - 38 - 41 - 49 - 52 - 57

2.3-2

重寫merge,使之不使用哨兵,而是一旦陣列l或r的所有元素均被複製回a就立刻停止,然後把另乙個陣列的剩餘部分複製回a。

解答:前面的大部分和原始的merge差不多,下面貼一下我寫的偽**

merge(a, p, q, r)

n1 = q - p + 1

n2 = r - q

let l[1...n1+1] and r[1...n2+1] be new arrays

for i from 1 to n1:

l[i] = a[p + i - 1]

for j from 1 to n2:

r[j] = a[q + j]

i = 1

j = 1

for k from p to r:

if l[i] <= r[j]:

a[k] = l[i]

i = i + 1

if i == n1 + 1:

break

else

a[k] = r[j]

j = j + 1

if j == n2 + 1:

break

if i == n1 + 1:

for j from j to r:

a[n1 + j] = r[j]

if j == n2 + 1:

for i from i to q:

a[n2 + i] = l[i]

2.3-3

使用數學歸納法證明:當n剛好是2的冪時,以下遞迴式的解是t(n) = nlgn.

t(n) =

2                      若 n = 2

2t(n/2) + n     若 n = 2^k, k > 1

解答:當n = 2^1時, t(n) = 2 <=> 2lg2 = 2

當n = 2^2時, t(n) = 2t(2^2/2) + 2^2 = 2t(2) + 4 = 2 * 2 + 4 = 8

nlgn = 2^2 * lg(2^2) = 4 * 2  = 8

左邊等於右邊

當n = 2^3時, t(n) = 2t(2^3/2) + 2^3 = 2t(4) + 8 = 2 * 8 + 8 =24

nlgn = 2^3 * lg(2^3) = 8 * 3 = 24

左邊等於右邊

當n = 2^n時, t(n)=2t(2^n/2) + 2^n = 2 * (2t(2^(n-1)/2) + 2^(n-1)) + 2^n = 4t(2^(n-1)/2) + 2 * 2^n = ... = 2^(n-1) * 2 + (n-1)*2^n = n2^n (t(n)的結果會使用到t(n-1)的值,依次類推)

nlgn = 2^n * lg(2^n) = n2^n

左邊等於右邊

1> 等n = 2時,t(n) = 2lg2 = 2成立

2> 假設當n=2^k(k > 1)時,等式成立,即t(2^k) = (2^k)lg(2^k) = k(2^k)

又因為已知n = 2^k(k > 1)時,有t(2^k) = 2t(2^k/2) + 2^k,

所以,t(2^(k+1)) = 2t(2^(k+1)/2) + 2^(k+1) = 2t(2^k) + 2^(k+1) = 2(k * 2^k) + 2^(k+1) = (k+1)*2^(k+1)

3> 所以,當n = 2^(k+1)時,等式也成立。

綜合①②,即遞迴式的解確實為t(n) = nlg(n)

2.3-4

我們可以把插入排序表示為如下的乙個遞迴過程。為了排序a[1...n], 我們遞迴地排序a[1...n-1],然後把a[n]插入已排序的陣列a[1..n-1]。

為插入排序的這個遞迴版本的最壞情況執行時間寫乙個遞迴式。

解答:這裡可以借鑑2.3-3中的結論。

這裡對a的前n-1個數進行遞迴排序。所以,前n-1個的遞迴式可以寫成

t(n-1)= 【這裡我們假設n-1為2的冪,主要是這樣能簡化解答過程】

2                              若 n - 1 = 2

2t((n-1)/2) + n -1  若 n -1 = 2^k, k>1

等待排序結束後,將a[n]插入。

這裡我們考慮的是最壞的運**況,所以,這個插入過程需要遍歷整個列表,也就是θ(n)。

結合兩個表示式,

t(n) =

5                                若n - 1 = 2

2t((n-1)/2) + 2n -1 若 n -1 = 2^k, k>1

ps. 想要獲得更一般的表示式可以參考20頁中的t(n)表示式進行求解。

2.3-5

回顧查詢問題,主意到,如果序列a已排好序,就可以將改序列的中點與v進行比較。根據比較的結果,原序列中有一半就可以不用再做進一步的考慮了。二分查詢演算法重複這個過程,每次都將序列剩餘部分的規模減半。為二分查詢寫出迭代或遞迴的偽**。證明:二分查詢的最壞情況執行時間為θ(lgn)。

解答:偽**寫起來比較簡單

binary(a[1..n], v):

low = 1, high = n

while low <= high:

mid = (low + high)/2

case:

a[mid] < t : low = mid + 1

a[mid] = t : return mid

a[mid] > t : high = mid - 1

return 0

這裡最壞的情況就是長度一直在對折,直到某一子段裡面只有乙個元素的時候。

在不停對折的過程中,就是一直對除以2,也就是lgn

這裡說的不是很直觀…… 當然在書中有圖可以看的更直觀一些。

在書的第21頁中,我們可以看到乙個樹狀圖,其實就可以看做是二分查詢的分解圖。

其深度也就是這個查詢的最壞情況所用的時間。

2.3-6

注意到2.1節中的過程insertion-sort的第5~7行的while迴圈採用一種線性查詢(反向)掃瞄已排好的子陣列a[1..j-1].我們可以使用二分查詢來把插入排序的最壞情況總執行時間改進到θ(nlgn)嗎?

解答:這裡應該是不行的。這裡查詢的時間複雜度是θ(nlgn)沒錯。不過,這裡不僅僅涉及到查詢,在排序的過程中(元素交換)時間複雜度並沒有減少,依舊是θ(n^2)。

如果採用的資料結果有高速的元素交換速度,那麼這個時間會相應的減少一些。

ps 在做這道題的時候不小心找到了這版的答案,也和大家共享一下吧 演算法導論第三版課後答案 這個有助於我們的對問題的解答,不過對於答案來說都是參考的,只有自己做出來才是自己的成果。

2.3-7

描述乙個執行時間為θ(nlgn)的演算法,給定n個整數的集合和另乙個整數x,該演算法能確定s中是夠存在兩個其和剛好為x的元素。

解答:這個是可以做的,不過提供的集合需要事先進行排序。

research-sum(s[1..n], x):

// s need sorted

for i from 1 to n:

index = binary(s, x - s[i])

if index && (s[i] + s[index] == x)

return true

return false

第二章 2 2節

2.2 1 用 記號表示函式n 3 1000 100n 2 100n 3 解答 這個就很簡單了,這裡我們真正感興趣的執行時間是增長率,也就是直接控制函式影象斜率的因素。這裡就是 n 3 2.2 2 考慮排序儲存在陣列a中的n個數 首先找出a中的最小元素並將a 1 中的元素進行交換。接著,找出a中的次...

第二章 第二節 注釋

零 怎麼編寫注釋 編寫注釋的方式有三種 1.以 開頭 2.以三個 開頭和結尾 3.以三個 開頭和結尾 定義乙個字串變數 name 張三 定義乙個函式 defgetname return name defsetname n param n 姓名 return name n defsetage age ...

第二章 2 3 快速排序

本節的主題是快速排序,他可能是應用廣泛的排序演算法了。優點 缺點 非常脆弱,在實現時要非常小心才能避免低劣的效能。與歸併排序的比較 快速排序與歸併排序是互補的 歸併排序將陣列分成兩個子陣列分別排序,並將有序的子陣列歸併並以整個陣列排序 而快速排序將陣列排序的方式則是當兩個子陣列都有序時整個陣列也就自...