109 年 國立臺灣大學資訊工程學系碩士班《資料結構與演算法》

📄 試題原卷 免費註冊後即可對照原始考卷 PDF免費註冊

第 1 題3 分

For i=1i = 1 to nn do
For j=1j = 1 to ii do
For k=1k = 1 to jj do
C[i][j][k]=A[i][j][k]+B[i][j][k]C[i][j][k] = A[i][j][k] + B[i][j][k];
end for
end for
end for

Let f(n)f(n) be the number of additions in the following algorithm.

  1. f(n)=O(n2n)f(n) = O(n^2\sqrt{n})
  2. f(n)=O(n2log⁡n)f(n) = O(n^2 \log n)
  3. f(n)=O(n3)f(n) = O(n^3)
  4. f(n)=O(nlog⁡n)f(n) = O(n \log n)
  5. f(n)=O(n100)f(n) = O(n^{100})

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查巢狀迴圈的執行次數,以及 Big-O 複雜度的計算。

每次執行最內層敘述

C[i][j][k]=A[i][j][k]+B[i][j][k]C[i][j][k] = A[i][j][k] + B[i][j][k]

會進行一次加法。因此,f(n)f(n) 等於三層迴圈實際執行的總次數。

關鍵在於各層迴圈的上限並非固定:

  • ii 從 11 到 nn
  • 固定 ii 後,jj 從 11 到 ii
  • 固定 i,ji,j 後,kk 從 11 到 jj

解題方法

固定某一個 ii 與 jj 時,最內層的 kk 會執行 jj 次。因此:

f(n)=∑i=1n∑j=1ijf(n)=\sum_{i=1}^{n}\sum_{j=1}^{i}j

先計算內層總和:

∑j=1ij=i(i+1)2\sum_{j=1}^{i}j=\frac{i(i+1)}{2}

所以:

f(n)=∑i=1ni(i+1)2=12∑i=1n(i2+i)f(n)=\sum_{i=1}^{n}\frac{i(i+1)}{2} =\frac{1}{2}\sum_{i=1}^{n}(i^2+i)

利用公式:

∑i=1ni=n(n+1)2\sum_{i=1}^{n}i=\frac{n(n+1)}{2} ∑i=1ni2=n(n+1)(2n+1)6\sum_{i=1}^{n}i^2=\frac{n(n+1)(2n+1)}{6}

得到:

f(n)=12(n(n+1)(2n+1)6+n(n+1)2)f(n) =\frac{1}{2} \left( \frac{n(n+1)(2n+1)}{6} + \frac{n(n+1)}{2} \right)

整理後:

f(n)=n(n+1)(n+2)6f(n)=\frac{n(n+1)(n+2)}{6}

其最高次項為:

16n3\frac{1}{6}n^3

因此:

f(n)=Θ(n3)f(n)=\Theta(n^3)

也就是:

f(n)=O(n3)f(n)=O(n^3)

選項分析

選項 1:f(n)=O(n2n)f(n)=O(n^2\sqrt n)

因為:

n2n=n5/2n^2\sqrt n=n^{5/2}

而實際執行次數為 Θ(n3)\Theta(n^3),n3n^3 的成長速度高於 n5/2n^{5/2},因此:

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 2 題3 分

Given two sorted list A and B (in increasing key order), the following recursive algorithm
merges A and B into a sorted list C (also in increasing key order).
• If either A or B is empty then the result is the other list.
• If both A or B are not empty, we compare the keys of the first nodes of A and B, and select the
smaller one (denoted as s), and remove it from the list. Then we recursively merge the remaining
parts of A and B into a new sorted list C', then we concatenate s with C' into the final sorted list
C.
Let f(n,m)f(n,m) be the minimum number of comparisons of this algorithm, where nn and mm are the numbers
of nodes in A and B respectively. f(n,m)f(n, m) is?

  1. Ω(n)\Omega(n)
  2. Ω(m)\Omega(m)
  3. Ω(n+m)\Omega(n + m)
  4. Ω(mn)\Omega(mn)
  5. Ω(mn(log⁡m+log⁡n))\Omega(mn(\log m + \log n))

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念:Merge 演算法之最佳狀況比較次數分析

  1. 遞迴合併機制:
    演算法每次比較串列 AA 與 BB 的第一個節點,選出較小者 ss 後,將剩餘節點遞迴合併。當 AA 或 BB 任一串列為空時,直接回傳另一串列,此基礎情況(Base Case)比較次數為 00。

  2. 最少比較次數 f(n,m)f(n, m) 推導:

    • 最佳狀況(Best Case):若串列 AA 的所有鍵值皆小於串列 BB 的第一個鍵值,則 AA 的 nn 個節點依次與 BB 的首項比較 nn 次後,AA 即變為空串列。
🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 3 題3 分

We now use the merge algorithm in the previous question to sort a set of keys. We first make
each key a list of a single node. Then we merge the first and the second lists into a sorted list of length
two, the third and the fourth lists into a sorted list of length two, and so on. If we start with nn keys now
we have roughly n/2n/2 sorted list of length two now. We then merge these lists of length two into roughly
n/4n/4 sorted list of length four, and so on. Finally we will have a sorted list of length nn. Let f(n)f(n) denote
the maximum possible total number of comparisons of this algorithm, then f(n)f(n) is? Note that all the
answers are in little-o notation.

  1. o(n)o(n)
  2. o(n/π)o(n/\pi)
  3. o(nlog⁡n)o(n \log n)
  4. o(n(log⁡n)2)o(n(\log n)^2)
  5. o(n2)o(n^2)

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查「合併排序法(merge sort)」的比較次數,以及漸進符號中的小 oo 定義。

兩個已排序串列合併時,最壞情況下必須比較到最後才完成,因此合併長度為 mm 的兩個串列,最多需要

m−1m-1

次比較。

每一層合併的總資料量約為 nn,所以每一層最多進行 O(n)O(n) 次比較;而串列長度每次加倍,總共約有 log⁡n\log n 層。因此

f(n)=Θ(nlog⁡n).f(n)=\Theta(n\log n).

解題方法

將合併過程依層次分析:

  • 第 11 層:由長度 11 的串列合併成長度 22,總比較次數為 O(n)O(n)。
  • 第 22 層:由長度 22 的串列合併成長度 44,總比較次數仍為 O(n)O(n)。
  • 第 kk 層:串列長度約為 2k2^k,總比較次數仍為 O(n)O(n)。
  • 串列長度從 11 增加到 nn,共約 log⁡n\log n 層。

因此:

f(n)=O(nlog⁡n).f(n)=O(n\log n).

同時,最壞情況下每一層都可達到與 nn 成正比的比較次數,故有下界:

f(n)=Ω(nlog⁡n).f(n)=\Omega(n\log n).

綜合得到:

f(n)=Θ(nlog⁡n).f(n)=\Theta(n\log n).

現在逐一檢查選項。小 oo 的定義是:

g(n)=o(h(n))  ⟺  lim⁡n→∞g(n)h(n)=0.g(n)=o(h(n)) \iff \lim_{n\to\infty}\frac{g(n)}{h(n)}=0.

選項分析

選項 1:o(n)o(n)

錯誤。因為

f(n)n=Θ(log⁡n)→∞,\frac{f(n)}{n} = \Theta(\log n)\to\infty,

所以 f(n)f(n) 不可能是 o(n)o(n)。


選項 2:o(n/π)o(n/\pi)

錯誤。由於 π\pi 是常數,

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 4 題3 分

A binary minimum heap is a binary tree in which every level is completely full, except the
last level, which is filled from the left to right. Here the level of a node is its distance to the root, so the
root has level 0 and the children of the root will have level 1, and so on. Also the key of a parent is less
than those of its children. For ease of discussion we assume that all keys in the heap are distinct. Now
which of the following descriptions about a binary minimum heap of 10 nodes (see the figure below) are
correct?
🖼️【此處有附圖,請對照原卷】

  1. The second smallest key is always in level 1.
  2. The largest key is always in a leaf, i.e., a node without any children.
  3. The second largest key is always in a leaf.
  4. Let nn be the number of nodes and we consider the case of arbitrary nn, then the height of the tree
    is O(log⁡n)O(\log n).
  5. Let nn be the number of nodes and we consider the case of arbitrary nn, then we can find the third
    smallest key of the heap by O(1)O(1) key comparisons.
🖼️ 本題含圖表,以下為原卷對應頁面:
原卷第 2 頁

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

最小堆同時滿足兩個條件:

  • 形狀性質:除了最底層外,各層都填滿;最底層由左至右填入。
  • 堆序性質:每個父節點的鍵值都小於其子節點。題目又說鍵值互異,因此大小關係明確。

堆序性質也會沿著路徑傳遞:任一祖先的鍵值都小於其後代。

解題方法

第 1、2、3、5 項利用堆序性質判斷鍵值可能的位置;第 4 項則利用完全二元樹的高度界。判斷「第二大」時,還要留意最底層由左至右填入後,某些非葉節點可能只有一個子節點。

選項分析

  1. 正確。 根節點是最小值。第二小的鍵值必在根的子節點中:任何更深的節點,都有一個根的子節點作為祖先,而該子節點的鍵值更小。因此,比較根的兩個子節點即可找出第二小值;此堆有 10 個節點,根有兩個子節點。

  2. 正確。 若最大值位於非葉節點,該節點至少有一個子節點,而子節點鍵值必比它大,與它是最大值矛盾。因此最大值必在葉節點。

  3. 錯誤。 此堆最底層從左至右填入 3 個節點,因此有一個非葉節點只有一個子節點。可將節點鍵值依層序排列為

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 5 題3 分

We will follow the notations from the previous question. We can build a heap from an array
of n keys by the following algorithm. A heapify operation for a binary minimum heap combines two
heaps and a root into a new heap. For ease of discussion we assume that the array is indexed from 1
to n, and the left/right child of a node with array index i have array indices 2i and 2i + 1 respectively.
We first set each key of the second half of the array (indexed from n/2 to n) as n/2 heaps, each has one
node. Then we combine two of them and their parent into a heap of three nodes, and so on. If the root
is smaller than the roots of both subtrees then we stop. Otherwise we exchange the root with the smaller
root from the subtrees, and repeatedly heapify the subtree where the root has just been replaced. Next
we heapify the key at n/2-1 and all the way back to the root (at index 1). The final result will be a
binary minimum heap of n nodes.

  1. The minimum number of key comparisons is O(n)O(n).
  2. The maximum number of key comparisons is O(n)O(n).
  3. Since each heapify on a key may compare it with all the keys down to a leaf, its number of
    comparisons is no more than the height of the heap, which is O(log⁡n)O(\log n). Also we have O(n)O(n) keys to
    heapify, so the total number of key comparisons is O(nlog⁡n)O(n \log n).
  4. The number of key comparisons is in the same order as the sum of (original, before heapified) levels
    (as defined in the previous question, the distance to the root) of all keys.

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查**由下而上建立二元堆積(Bottom-Up Build-Heap / Floyd's Algorithm)**的比較次數與時間複雜度分析,核心概念包含:

  1. 堆積調整(Heapify / Sift-Down)之成本:
    在高度為 hh 的節點上執行一次 Heapify,其元素最多往下沉 hh 層。每下沉一層需要先比較左右子節點(1 次比較),再將較小(或較大)者與當前父節點比較(1 次比較),因此單層至多需要 22 次鍵值比較。故在高度為 hh 的節點執行 Heapify,比較次數上界為 O(h)O(h)。
  2. 節點高度(Height)與節點深度/層級(Depth / Level)的區別:
    • 高度(Height, hh):節點到其子樹中最遠葉節點的路徑長度(葉節點 h=0h=0)。
    • 深度/層級(Depth / Level, dd):根節點到該節點的路徑長度(根節點 d=0d=0)。
    • 由下而上建堆的比較次數與各節點的高度總和(Sum of Heights)成正比,而非深度總和(Sum of Depths)。
  3. 收斂級數求和:
    計算最差情況時,利用等比差級數求和公式: ∑h=1∞h2h=2\sum_{h=1}^{\infty} \frac{h}{2^h} = 2 證明 Bottom-Up 建堆的總比較次數在最差情況下為 Θ(n)=O(n)\Theta(n) = O(n)。

解題方法與數學推導

1. 最佳情況(Best-Case)分析

  • 情境:若輸入陣列本來就已經滿足 Min-Heap 的性質(例如所有節點皆小於其子節點)。
  • 推導:
    演算法依序對 index ⌊n/2⌋\lfloor n/2 \rfloor 遞減至 11 的所有內部節點進行 Heapify。每個內部節點在比較左右子節點並與根比較後,發現根節點已是最小值,即立刻停止下沉(下沉深度為 0)。
    共有 ⌊n/2⌋\lfloor n/2 \rfloor 個內部節點,每個節點固定做 1∼21 \sim 2 次比較: Tmin⁡(n)≥1×⌊n2⌋=Ω(n)T_{\min}(n) \ge 1 \times \left\lfloor \frac{n}{2} \right\rfloor = \Omega(n) 因此最佳情況的比較次數為 Θ(n)\Theta(n),滿足 O(n)O(n)。

2. 最差情況(Worst-Case)分析

  • 情境:每次 Heapify 的節點都需要一路下沉至葉節點。
  • 推導:
    在包含 nn 個節點的完全二元樹中,高度為 hh 的節點數量上限為 ⌈n2h+1⌉\left\lceil \frac{n}{2^{h+1}} \right\rceil,樹高為 ⌊log⁡2n⌋\lfloor \log_2 n \rfloor。
    每個高度為 hh 的節點最多進行 2h2h 次比較,總比較次數 Tmax⁡(n)T_{\max}(n) 滿足: Tmax⁡(n)≤∑h=1⌊log⁡2n⌋⌈n2h+1⌉⋅2h≤∑h=1∞n2h⋅h=n∑h=1∞h2hT_{\max}(n) \le \sum_{h=1}^{\lfloor \log_2 n \rfloor} \left\lceil \frac{n}{2^{h+1}} \right\rceil \cdot 2h \le \sum_{h=1}^{\infty} \frac{n}{2^h} \cdot h = n \sum_{h=1}^{\infty} \frac{h}{2^h} 令 S=∑h=1∞h2h=12+24+38+416+…S = \sum_{h=1}^{\infty} \frac{h}{2^h} = \frac{1}{2} + \frac{2}{4} + \frac{3}{8} + \frac{4}{16} + \dots
    將兩邊同乘 12\frac{1}{2}: 12S=14+28+316+…\frac{1}{2}S = \frac{1}{4} + \frac{2}{8} + \frac{3}{16} + \dots 兩式相減: S−12S=12+14+18+116+⋯=1  ⟹  S=2S - \frac{1}{2}S = \frac{1}{2} + \frac{1}{4} + \frac{1}{8} + \frac{1}{16} + \dots = 1 \implies S = 2 代回得:
🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 6 題3 分

A randomized quick sort works as follows. For ease of discussion we assume that the sequence
we want to sort, K = (k1,...,knk_1,..., k_n), is a permutation of 1 to n. We randomly and uniformly pick a key
k from K. Then we partition K into two subsets K₁ that has keys less than k and K₂ that has keys
greater than k. Then we recursively sort K₁ and K₂, and combine the results with k to get the sorted
sequence.

  1. The number of key comparisons will always be maximized when the keys in K are already sorted.
  2. Let K1K_1 and K2K_2 be the number of keys in K1K_1 and K2K_2 respectively. The expected value of
    max(K1,K2K_1, K_2]) is nn.
  3. The algorithm will compare two keys kik_i and kjk_j at most once, so the number of key comparisons is O(n2)O(n^2).
  4. The probability that the algorithm will compare kik_i and kjk_j (n≥i>j≥1n \ge i > j \ge 1) is 2n+1\frac{2}{n+1}.
  5. Let P={(i,j)∣1≤i,j≤n,i≠j}P = \{(i,j)| 1 \le i, j \le n, i \neq j\}. The expected total number of key comparisons is ∑(i,j)∈P2n+1\sum_{(i,j) \in P} \frac{2}{n+1}.

登入後即可作答並保存紀錄。

這一題的完整詳解

各選項詳細分析如下:

  1. 錯誤。隨機快速排序(Randomized Quick Sort)係隨機均勻選擇樞紐碼(Pivot),比較的最多次數(最壞情況 O(n2)O(n^2))取決於隨機挑選 Pivot 的過程是否每次皆選到極值,與輸入序列 KK 原始是否已排序無關。

  2. 錯誤。設 Pivot 之排名為 r∈{1,2,…,n}r \in \{1, 2, \dots, n\},挑選至各排名的機率皆為 1n\frac{1}{n}。此時子集合大小分別為 ∣K1∣=r−1|K_1| = r - 1 與 ∣K2∣=n−r|K_2| = n - r。期望值計算如下:
    E[max⁡(∣K1∣,∣K2∣)]=1n∑r=1nmax⁡(r−1,n−r)≈34n≠nE[\max(|K_1|, |K_2|)] = \frac{1}{n} \sum_{r=1}^n \max(r-1, n-r) \approx \frac{3}{4}n \neq n

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 7 題3 分

We can use a linked list to implement a stack. We assume that we use structure Node with
two members to store the data, and the member next points to the next node in the linked list. Also we use a variable head to point to the first node of the linked list. head is initialized to NULL.

  1. Pushing the value of a variable i into the stack can be implemented as follows.
    newHead = malloc(sizeof (Node));
    newHead->data = i;
    newHead->next = head;
    head = newHead;
  2. Popping the top of the stack into a variable i can be implemented as follows.
    free (head);
    i = head->data;
    head = head->next;
  3. To test if the stack is empty we can check if the head is a NULL pointer.
  4. We can improve the push/pop efficiency of this stack by adding another pointer tail that points
    to the end of the linked list, so we can access the last node in the list in O(1) time.
  5. We can improve the push/pop efficiency of this stack by adding another pointer member into every
    node, so it becomes a double linked list. That is, we can traverse in both directions in this linked
    list.

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查:

  • Linked list 實作 Stack 的方式
  • Stack 的 LIFO(Last-In, First-Out)
  • Push 與 pop 的時間複雜度
  • 指標操作與動態記憶體管理
  • Singly linked list 與 doubly linked list 的差異

以 head 指向 linked list 第一個節點時,最適合將 head 視為 stack 的頂端:

  • Push:將新節點插入 head 前方
  • Pop:移除 head 所指的節點
  • Empty:檢查 head == NULL

因此 push 與 pop 都能在 O(1)O(1) 時間完成。


解題方法

逐一檢查每個敘述:

  1. 是否正確維持 stack 的 LIFO 結構?
  2. 是否正確操作 linked list 指標?
  3. 是否有違反 C 語言動態記憶體使用規則?
  4. 是否真的改善了時間複雜度?

選項分析

1. Push 實作

newHead = malloc(sizeof(Node));
newHead->data = i;
newHead->next = head;
head = newHead;

此敘述正確。

原本 stack:

head → A → B → NULL

建立新節點後:

newHead → i

令:

newHead->next = head;

得到:

newHead(i) → A → B → NULL

最後:

head = newHead;

新的節點成為 stack top,符合 LIFO。

時間複雜度為:

Tpush=O(1)T_{\text{push}} = O(1)

空間複雜度為:

O(1)O(1)

其中 O(1)O(1) 是指此次 push 額外配置一個節點。


2. Pop 實作

free(head);
i = head->data;
head = head->next;

此敘述錯誤。

free(head) 會釋放 head 所指向的記憶體。釋放後,head 仍可能保留原本的位址,但該位址已經不能再存取,因此後續:

i = head->data;
head = head->next;

都是對已釋放記憶體的存取,屬於 use-after-free,會造成未定義行為。

正確順序應為:

i = head->data;
oldHead = head;
head = head->next;
free(oldHead);

也可寫成:

i = head->data;
Node *oldHead = head;
head = head->next;
free(oldHead);

若要處理空 stack,還必須先檢查:

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 8 題3 分

A randomized linked list sorting algorithm works as follows. We want to build a linked list
in which the keys are in increasing order. That is, every node has a smaller key than its successor in
the list. For ease of discussion we assume that the keys are distinct integers from 1 to n. The algorithm
randomly picks a key from the remaining keys, and inserts it into the list. This process repeats until all
keys are inserted. The inserted key k will skip those at the beginning of the list that are smaller than
it, and will stop at the first key p that are greater than it. We then insert the key k before p. To ensure
that all keys will stop we assume that initially the list has only one key, n + 1. After we insert all keys
we will have a sorted linked list from 1 to n + 1.

  1. Every inserted key will stop exactly once.
  2. The smallest key 1 will not skip any keys.
  3. The largest key n will always skip n-1 keys.
  4. The expected number of keys that the key i will skip is O(i)O(i).
  5. The key i will skip j if and only if i > j and i is inserted after j is inserted, so the expected value
    of the total number of key comparisons is O(n2)O(n^2).

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查隨機插入(randomized insertion)與期望值分析。

插入鍵值 kk 時,串列目前維持嚴格遞增,因此:

  • 所有已插入且小於 kk 的鍵,都位於 kk 的前方,會被跳過。
  • 第一個大於 kk 的鍵會讓搜尋停止。
  • 初始的哨兵鍵 n+1n+1 大於所有待插入鍵,因此每次搜尋必定能停止。

假設 1,2,…,n1,2,\ldots,n 的插入順序為隨機排列,任兩個不同鍵的先後順序皆等機率。


解題方法

對任意鍵 ii 而言,考慮每個較小鍵 j<ij<i:

  • 若 jj 先於 ii 插入,則 jj 已在串列中,且 j<ij<i,所以 ii 一定會跳過 jj。
  • 若 ii 先於 jj 插入,則 jj 尚未存在,ii 不可能跳過 jj。

因此,鍵 ii 跳過的鍵數為:

Xi=#{j:1≤j<i, j 先於 i 插入}.X_i=\#\{j:1\le j<i,\ j\text{ 先於 }i\text{ 插入}\}.

對每個 j<ij<i,jj 先於 ii 的機率為 1/21/2,所以由期望值線性性:

E[Xi]=∑j=1i−1P(j 先於 i)=∑j=1i−112=i−12.E[X_i] =\sum_{j=1}^{i-1}P(j\text{ 先於 }i) =\sum_{j=1}^{i-1}\frac12 =\frac{i-1}{2}.

因此:

E[Xi]=O(i).E[X_i]=O(i).

此外,每次插入除了比較並跳過較小鍵之外,還必須與第一個大於它的鍵比較一次才能停止。因此總比較次數至多為「總跳過次數加上 nn 次停止比較」:

E[總比較次數]=∑i=1nE[Xi]+O(n)E[\text{總比較次數}] =\sum_{i=1}^{n}E[X_i]+O(n) =∑i=1ni−12+O(n)=n(n−1)4+O(n)=O(n2).=\sum_{i=1}^{n}\frac{i-1}{2}+O(n) =\frac{n(n-1)}{4}+O(n) =O(n^2).

選項分析

1. Every inserted key will stop exactly once.

正確。

由於串列始終維持遞增,插入鍵 kk 時,搜尋會在第一個大於 kk 的鍵處停止。即使目前沒有其他大於 kk 的鍵,哨兵鍵 n+1n+1 也一定存在,且滿足 n+1>kn+1>k。

每個鍵只進行一次由頭到尾的搜尋,因此會且只會停止一次。


2. The smallest key 1 will not skip any keys.

正確。

鍵 11 是最小鍵,串列中不存在比它更小的鍵。因此搜尋從串列開頭開始時,第一個節點必定大於 11,鍵 11 不會跳過任何鍵。

X1=0.X_1=0.

3. The largest key n will always skip n-1 keys.

錯誤。

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 9 題3 分

A binary search tree is a tree where every node has at most two children. For ease of discussion
we assume that every node has a distinct key. In addition, all keys in the left subtree are smaller than
the key of root, and all keys in the right subtree are larger than the key of the root. A tree node is a leaf
if it does not have any children. The height of the tree is the length of the longest path from the root to
a leaf. The successor of a node z is the node right after in increasing order, and the predecessor of a
node z is the node right before x in increasing order.

  1. We can locate the smallest key in a binary search tree in O(h)O(h) time in the worst case, where h is
    the height of the tree.
  2. The height of a binary search tree of n nodes is O(log⁡n)O(\log n).
  3. We can locate the largest key in a binary search tree in O(log⁡n)O(\log n) time in the worst case, where n is
    the number of the nodes in the tree.
  4. Assume that a node z has two children. We can remove z while still maintaining the sorted order
    by locating its successor y, connecting y's parent directly to the only child of y (if there is one,
    otherwise make it null), which effectively removes the node y from the tree, and replacing the key
    of z with that of y.
  5. Assume that a node z has two children. We can remove z while still maintaining the sorted order
    by locating its predecessor y, connecting y's parent directly to the only child of y (if there is one,
    otherwise make it null), which effectively removes the node y from the tree, and replacing the key
    of z with that of y.

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查二元搜尋樹(Binary Search Tree, BST)的:

  • 搜尋最小值與最大值的方法及時間複雜度。
  • 樹高與節點數的關係。
  • 使用 successor(後繼)或 predecessor(前驅)刪除具有兩個子樹的節點。
  • BST 的排序性質:
左子樹所有鍵值<根節點鍵值<右子樹所有鍵值\text{左子樹所有鍵值} < \text{根節點鍵值} < \text{右子樹所有鍵值}

BST 的中序走訪結果會依鍵值遞增排列,因此 successor 是中序順序的下一個節點,predecessor 是中序順序的上一個節點。


解題方法

判斷搜尋複雜度時,沿著樹的一條路徑向下尋找,因此時間複雜度通常為 O(h)O(h),其中 hh 是樹高。只有在樹高本身為 O(log⁡n)O(\log n) 時,才能進一步寫成 O(log⁡n)O(\log n)。

刪除具有兩個子女的節點時,可用其中序後繼或中序前驅的鍵值取代該節點,再刪除後繼或前驅原本所在的節點。這是因為:

  • successor 位於右子樹中最左側的位置,因此沒有左子女,最多只有右子女。
  • predecessor 位於左子樹中最右側的位置,因此沒有右子女,最多只有左子女。

所以被移除的 successor 或 predecessor 一定至多只有一個子女,能以一般的「單子女節點刪除」方式處理。


選項分析

1. 正確

BST 中最小鍵值必定位於最左側。從根節點開始,不斷沿著 left pointer 往下走,直到目前節點沒有左子女為止:

最小鍵值節點=最左側節點\text{最小鍵值節點} = \text{最左側節點}

最多走過從根到葉節點的一條路徑,因此最壞時間複雜度為:

O(h)O(h)

所以此敘述正確。


2. 錯誤

一般二元搜尋樹不保證平衡。若每次插入的鍵值都比前一個大,例如依序插入:

1,2,3,…,n1,2,3,\ldots,n

形成的 BST 會退化成鏈狀:

1→2→3→⋯→n1 \rightarrow 2 \rightarrow 3 \rightarrow \cdots \rightarrow n

此時樹高為:

h=n−1=O(n)h=n-1=O(n)

只有平衡二元搜尋樹的高度才是 O(log⁡n)O(\log n))。一般 BST 的高度最壞情況為 O(n)O(n),因此此敘述錯誤。


3. 錯誤

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 10 題3 分

A red-black tree is a binary tree where every node has a color (red or black), and has the
following properties.

  1. The root is black.
  2. All paths from the root to a leaf have the same number of black nodes.
  3. Every red node must have two black children.
    For ease of discussion we assume that all null pointers (a special pointer to "nothing") point to a special
    black node. As a result all counting of the second property ends at this special node.
  4. If we do not guarantee the first property, but still guarantee the second and the third properties,
    we will not be able to guarantee that the height of the tree is O(log⁡n)O(\log n).
  5. It is possible that there are no red nodes in a red-black tree of 100000 nodes.
  6. We insert a key k into a non-empty red-black tree just like into an ordinary binary search tree as
    a leaf, attach to it two null pointers to the special black node, and then immediately stop without
    any adjustment. If we color k red, we may violate the second property above.
  7. Consider the scenario above. If we color k red, we may violate the third property above.
  8. Consider the scenario above. If we color k black, we will violate the second property above.

登入後即可作答並保存紀錄。

這一題的完整詳解

各選項詳細推導如下:

  1. 錯誤。若根節點改為紅色,但仍維持屬性 2(所有路徑黑節點數相同)與屬性 3(無連續紅節點),設黑高度為 bhbh。由於紅節點不得連續,樹高滿足 h≤2⋅bh+1h \le 2 \cdot bh + 1。又由黑色節點構成的樹結構可知內部節點數 n≥2bh−1  ⟹  bh≤log⁡2(n+1)n \ge 2^{bh} - 1 \implies bh \le \log_2(n+1),故樹高仍保證為 h≤2log⁡2(n+1)+1=O(log⁡n)h \le 2\log_2(n+1) + 1 = O(\log n)。

  2. 錯誤。若紅黑樹中無任何紅節點,則所有節點皆為黑節點。根據屬性 2,從根節點到每個 NULL 節點的路徑黑節點數必須相等,即所有路徑長度皆為 hh,此樹必為完美二元樹(Perfect Binary Tree)。其內部節點總數必須符合 n=2h−1n = 2^h - 1。

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 11 題5 分

Given an array of n integers A = (a1,a2,...,ana_1, a_2, ..., a_n) (n>0n > 0), you are asked to find the maximum
and minimum elements with minimum comparisons. A simple solution is to iteratively compare each
element with current max and min. It takes 2n comparisons in total.
(a) (3 points) Devise an algorithm that requires less than 1.67n comparisons.
(b) (2 points) How many comparisons does your algorithm take? Show your derivation.

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

這題考的是「成對比較(pairwise comparison)」找最大值與最小值。

若逐一處理每個元素,每個元素都必須分別與目前最大值、最小值比較,約需 2n2n 次比較。改進方法是先把元素兩兩分組:

  1. 先比較同一對中的兩個元素,判定誰較小、誰較大。
  2. 較小者只需與目前最小值比較。
  3. 較大者只需與目前最大值比較。

因此,每一對元素只需 33 次比較,而不是 44 次。


解題方法

將陣列分成若干組,每組包含兩個元素。對於一組 (x,y)(x,y):

  • 若 x<yx<y,則令 low=xlow=x、high=yhigh=y;
  • 否則令 low=ylow=y、high=xhigh=x。

接著執行:

  • 比較 lowlow 與目前的最小值;
  • 比較 highhigh 與目前的最大值。

如此每處理一對元素,固定使用 33 次比較。

關鍵虛擬碼如下:

if n = 1:
    min = max = A[1]

else if n is even:
    compare A[1] and A[2]
    initialize min and max
    i = 3

else:
    min = max = A[1]
    i = 2

while i <= n:
    compare A[i] and A[i+1]
    let low be the smaller element
    let high be the larger element

    compare low with min
    compare high with max

    i = i + 2

return min, max

若一對元素相等,任意指定其中一個為 lowlow、另一個為 highhigh,仍不影響正確性。


正確性說明

處理完每一對元素後,該對的較小元素一定不可能成為整體最大值,因此只需拿來更新最小值;同理,該對的較大元素一定不可能成為整體最小值,因此只需拿來更新最大值。

維持以下不變量:

  • min 是目前已處理元素中的最小值;
  • max 是目前已處理元素中的最大值。

每處理一對新元素後:

  • 較小者與 min 比較,確保最小值正確;
  • 較大者與 max 比較,確保最大值正確。
🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 12 題15 分

There are n stations along a coastal railway (n > 0). You're planning to select some of them
to open cafes. Three arrays S, L and R have been given, including
S = (s1,s2,...,sns_1, s_2, ..., s_n): the list of the stations froin s1s_1 (first) to sns_n (last).
L = (l1,l2,...,lnl_1, l_2, ..., l_n): the locations of the stations, where lil_i is the distance of sis_i from the first station
s1s_1. So l1=0l_1 = 0 and lnl_n is the length of the railway. l1<l2<...<lnl_1 < l_2 < ... < l_n.
R = (r1,r2,...,rnr_1, r_2, ..., r_n): the revenues of the cafes, where ri(>0)r_i (>0) is the revenue for opening a cafe in sis_i.
The only one constraint in your plan is that the distance of any pair of your selected stations should be
longer than a given threshold T. If sis_i and sjs_j (i≠ji \neq j) are selected, the total revenue would be li+ljl_i + l_j.
Different selection leads to different total revenue. Given S, L, R and T, your goal is to pick up a
subset of the stations to maximize the total revenue under the constraint. Suppose that f(n)f(n) returns
the maximum total revenue for the cafes you select from the first n stations. Please answer the following
questions. No code is required (code will not be graded).
(a) (9 points) Give an O(n2)O(n^2) solution by defining a recurrence formula for f(n)f(n). Clearly explain the
meaning of your formula and why it can be computed in O(n2)O(n^2) time.
(b) (6 points) Consider the special case that the distance difference between two consecutive stations
is 1, i.e., li+1−li=1l_{i+1}- l_i=1 (1≤i≤n−11 \le i \le n - 1). Give an O(n)O(n) solution by defining a recurrence formula for
f(n)f(n). Clearly explain the meaning of your formula and why it can be computed in O(n)O(n) time.

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題是「排序後的加權間隔選擇」問題:

  • 車站已依位置排序:l1<l2<⋯<lnl_1<l_2<\cdots<l_n。
  • 每個車站 sis_i 有收益 rir_i。
  • 任兩個被選車站的距離必須嚴格大於 TT。
  • 目標是在合法選擇中,使總收益最大。

題幹中「total revenue would be li+ljl_i+l_j」應為筆誤;收益陣列已定義為 R=(r1,…,rn)R=(r_1,\ldots,r_n),以下依正確意義使用總收益 ∑ri\sum r_i。

令

f(i)=只考慮前 i 個車站時,可得到的最大總收益f(i)=\text{只考慮前 }i\text{ 個車站時,可得到的最大總收益}

並設定

f(0)=0。f(0)=0。

由於所有 ri>0r_i>0,選擇一個車站的收益為 rir_i。


(a) O(n2)O(n^2) 解法

對每個車站 sis_i,定義

p(i)=max⁡{j<i∣li−lj>T},p(i)=\max\{j<i\mid l_i-l_j>T\},

若不存在符合條件的 jj,則令 p(i)=0p(i)=0。

p(i)p(i) 表示:在選擇車站 sis_i 時,所有可能與它同時被選的較早車站,都必須位於前 p(i)p(i) 個車站之中。

因此,考慮前 ii 個車站時有兩種情況:

  1. 不選擇 sis_i

    此時收益為

    f(i−1)。f(i-1)。
  2. 選擇 sis_i

    由於任一先前選取的車站必須滿足與 sis_i 的距離大於 TT,先前可選的車站只能來自前 p(i)p(i) 個車站。因此收益為

    ri+f(p(i))。r_i+f(p(i))。

得到遞迴式:

f(i)=max⁡(f(i−1), ri+f(p(i)))\boxed{ f(i)=\max\bigl(f(i-1),\ r_i+f(p(i))\bigr) }

最後答案為 f(n)f(n)。

為何遞迴式正確

任一個最佳解若不包含 sis_i,其收益至多為 f(i−1)f(i-1)。

若最佳解包含 sis_i,則其餘被選車站必須全部位於前 p(i)p(i) 個車站中;否則若存在 sjs_j 且 j>p(i)j>p(i),便有

li−lj≤T,l_i-l_j\le T,

違反距離必須嚴格大於 TT 的限制。因此,其餘車站的最大收益為 f(p(i))f(p(i)),總收益為 ri+f(p(i))r_i+f(p(i))。

兩種情況取最大值即可涵蓋所有合法選擇。

時間複雜度

每個 p(i)p(i) 可以由向前掃描求得,最多檢查 i−1i-1 個車站,因此所有 p(i)p(i) 的計算時間為

O(1+2+⋯+n)=O(n2)。O(1+2+\cdots+n)=O(n^2)。

之後每個 f(i)f(i) 只需 O(1)O(1) 時間計算,所以總時間複雜度為

O(n2)。\boxed{O(n^2)}。

若使用陣列儲存 f(0),f(1),…,f(n)f(0),f(1),\ldots,f(n),空間複雜度為 O(n)O(n)。


🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 13 題15 分

A disjoint-set data structure supports two operations. One is UNION(x, y), which merges
the two roots of the trees containing and y. The other is FIND(x), which returns the root of the tree
containing z. Union-by-height is a union heuristic, which keeps track of the heights of the trees to attach
the shorter tree to the root of the taller tree.
(a) (9 points) Given an undirected graph G = (V, E), where V = {v1, ..., vm} (m > 0) and E = {e1,..., en} (n > 0), devise an algorithm to check if the graph G is a tree or not by using
UNION(vi, vj) with union-by-height and FIND(x) with no path compression, where vi, vj and
UKE V. Clearly describe your solution and analyze the time complexity of your algorithm in the
worst case. No code is required (code will not be graded).
(b) (6 points) The union-by-height heuristic prevents the height of a tree from growing linearly. Consider
another heuristic, called union-by-descendant, which always attaches the tree with fewer descen-
dants to the root of the tree with more descendants. Suppose that path compression is not applied.
Which of the two heuristics is asymptotically better? Why?

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考查:

  • Disjoint-set data structure(不相交集合)
  • FIND 判斷兩個頂點是否已在同一棵樹中
  • UNION 合併不同的連通元件
  • Union-by-height 的樹高分析
  • 無向圖成為樹的判定條件

無向圖 G=(V,E)G=(V,E) 是樹,當且僅當:

  1. GG 是連通圖;
  2. GG 不含 cycle。

也可利用等價條件:若圖連通且 ∣E∣=∣V∣−1|E|=|V|-1,則圖為樹。不過本題要求使用 UNION 與 FIND,因此應明確檢查是否產生 cycle,以及最後是否只剩一個連通元件。


(a) 使用 Disjoint Set 判斷是否為樹

解題方法

首先為每個頂點建立一個獨立集合:

{v1},{v2},…,{vm}\{v_1\},\{v_2\},\ldots,\{v_m\}

每個集合代表目前的一個連通元件。

依序處理每條邊 ek=(vi,vj)e_k=(v_i,v_j):

  1. 計算 ri=FIND⁡(vi)r_i=\operatorname{FIND}(v_i);
  2. 計算 rj=FIND⁡(vj)r_j=\operatorname{FIND}(v_j);
  3. 若 ri=rjr_i=r_j,表示 viv_i 與 vjv_j 已經在同一棵樹中,加入邊 (vi,vj)(v_i,v_j) 會形成 cycle,因此直接判定 GG 不是樹;
  4. 若 ri≠rjr_i\neq r_j,執行:
UNION⁡(vi,vj)\operatorname{UNION}(v_i,v_j)

並將兩個連通元件合併。

所有邊處理完後,檢查是否只剩一個集合:

  • 若只有一個集合,表示圖連通,且處理過程中沒有形成 cycle,因此 GG 是樹;
  • 若仍有兩個以上集合,表示圖不連通,因此 GG 不是樹。

可用變數 components 記錄連通元件數,初始為 mm。每次成功合併兩個不同集合時,令:

components←components−1\text{components} \leftarrow \text{components}-1

最後檢查:

components=1\text{components}=1

正確性說明

若某條邊 (vi,vj)(v_i,v_j) 處理時滿足:

FIND⁡(vi)=FIND⁡(vj)\operatorname{FIND}(v_i)=\operatorname{FIND}(v_j)

則兩點之間原本已有一條路徑,再加入直接連接兩點的邊,必然形成 cycle。

反之,若每條邊都連接兩個不同集合,則每次加入的邊都只會合併兩個連通元件,不會產生 cycle。

因此:

  • 所有邊處理完且沒有發現 cycle:圖為森林;
  • 森林最後只有一個連通元件:圖連通;
  • 連通且無 cycle:圖為樹。

時間複雜度

Union-by-height 保證集合樹的高度為 O(log⁡m)O(\log m)。

證明如下:當一棵樹的高度增加 11 時,只有在兩棵高度相同的樹合併時才會發生。此時新樹的節點數至少加倍,因此高度為 hh 的樹至少包含 2h2^h 個節點:

2h≤m2^h\le m

所以:

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 14 題20 分

A tree T is assumed to be simple, undirected, and with positive edge-weights. Let dr(u, v)
denote the distance between u and v on T. For a vertex v, the eccentricity of v is the maximum of the
distance to any vertex in the tree, i.e., max ev{dr(v, u)}. The diameter of a tree is the maximum
of the eccentricity of any vertex in the tree. (The term "diameter" is overloaded. It is defined as the
maximum eccentricity and also as the path of length equal to the maximum eccentricity.) The radius of
a tree is the minimum eccentricity among all vertices in the tree, and a center of a tree is a vertex with
eccentricity equal to the radius.
(a) (5 points) Prove or disprove that there exists a tree with three different diameters and two centers.
(b) (5 points) Prove or disprove that there exists a tree with three centers.
(c) (10 points) Prove or disprove that any center of a given tree T must lie in the diameter of T.

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

設樹的直徑長度為 DD,直徑路徑兩端為 s,ts,t。樹的正權重保證任兩點間最短路徑唯一。

本題使用以下重要性質:

若 s,ts,t 是任一直徑路徑的兩端,則對任意頂點 vv,
e(v)=max⁡{d(v,s),d(v,t)}.e(v)=\max\{d(v,s),d(v,t)\}.

理由如下。取任意頂點 uu,令 qq 為 s,t,us,t,u 三條路徑的分岔點,並設

A=d(q,s),B=d(q,t),C=d(q,u).A=d(q,s),\qquad B=d(q,t),\qquad C=d(q,u).

由於 ss 到 tt 是直徑,必有

A+B≥A+C,A+B≥B+C,A+B\ge A+C,\qquad A+B\ge B+C,

因此 A≥CA\ge C 且 B≥CB\ge C。依照 vv 所在的分支,可知 ss 或 tt 至少有一個滿足

d(v,s)≥d(v,u)或d(v,t)≥d(v,u).d(v,s)\ge d(v,u) \quad\text{或}\quad d(v,t)\ge d(v,u).

所以離 vv 最遠的頂點一定可由 s,ts,t 其中之一取得,故上式成立。


(a) 是否存在具有三條不同直徑且有兩個中心的樹?

存在。

構造一棵樹如下:

  • 中央邊為 a−ba-b,權重為 22。
  • aa 分別連接葉節點 x1,x2x_1,x_2,每條邊權重為 11。
  • bb 分別連接葉節點 y1,y2y_1,y_2,每條邊權重為 11。

其結構可表示為:

x1, x2⟶a→ 2 b⟵y1, y2x_1,\ x_2 \longrightarrow a \xrightarrow{\ 2\ } b \longleftarrow y_1,\ y_2

其中所有葉節點與 a,ba,b 的邊權重皆為 11。

任取 xix_i 與 yjy_j,其距離為

d(xi,yj)=1+2+1=4.d(x_i,y_j)=1+2+1=4.

因此下列四條路徑都是長度 44 的直徑:

x1−a−b−y1,x_1-a-b-y_1, x1−a−b−y2,x_1-a-b-y_2, x2−a−b−y1,x_2-a-b-y_1, x2−a−b−y2.x_2-a-b-y_2.

特別地,至少有三條不同直徑。

接著計算各頂點的離心率:

e(a)=max⁡{d(a,x1),d(a,x2),d(a,y1),d(a,y2)}=max⁡{1,1,3,3}=3,e(a)=\max\{d(a,x_1),d(a,x_2),d(a,y_1),d(a,y_2)\} =\max\{1,1,3,3\}=3, e(b)=3.e(b)=3.

而對任一葉節點,例如 x1x_1,

e(x1)=d(x1,y1)=4.e(x_1)=d(x_1,y_1)=4.

因此半徑為

r=3,r=3,

且中心恰為 a,ba,b 兩個頂點。


(b) 是否存在具有三個中心的樹?

不存在。

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

其他考古題