113 年 國立高雄大學資訊工程學系碩士班《離散數學與資料結構》
第 1 題5 分
Assuming that x is an array and ptr is a pointer to that array, what expression refers to the address of the fifth element of x?
(a) *(ptr+4)
(b) ptr[5]
(c) &x[4]
(d) *(x+4)
登入後即可作答並保存紀錄。
核心觀念
陣列元素採用「從 開始編號」:
因此,第五個元素是 。
陣列名稱在運算式中通常會退化為指向第一個元素的指標,因此:
其中:
- :取得第五個元素的位址。
- :取得第五個元素的值。
- :取得第五個元素的值。
- 若 指向 ,則 是第五個元素的位址,而 是第五個元素的值。
解題方法
題目要求的是「第五個元素的地址」。
由於陣列索引從 開始,第五個元素為:
取得該元素的地址需使用取址運算子 :
此外,陣列指標運算也可表示為:
所以正確表達式是:
選項分析
(a) *(ptr+4)
若 指向陣列第一個元素 ,則:
第 2 題15 分
A linked list is given below:
🖼️【此處有附圖,請對照原卷】
Please describe what happens if we apply the following two consecutive statements to the linked list above.
z ← (*z).link
z ← (*z).link
登入後即可作答並保存紀錄。
核心觀念
此題考察單向 linked list 的指標走訪。若節點結構為:
其中 link 指向下一個節點,z 則是目前所在節點的指標。
解題方法
第一行:
z ← (*z).link
將 z 更新為目前節點的下一個節點,因此指標向後移動一次。
第二行:
z ← (*z).link
再從目前節點向後移動一次。
設原本:
則執行過程為:
第 3 題20 分
Given two arrays x and y where the size (i.e., the number of elements) of x and y is m and n, respectively, please propose an efficient algorithm to find the common elements in x and y. Discuss the computational complexity of your algorithm.
登入後即可作答並保存紀錄。
核心觀念
本題考查陣列的交集(intersection)與雜湊表(hash table)查找。
給定陣列:
- 的大小為
- 的大小為
目標是找出同時出現在 與 中的元素。若陣列可能含有重複值,通常將「common elements」視為集合交集,因此每個共同元素只輸出一次。
雜湊表平均可在 時間內完成查找,因此適合用來加速元素是否存在的判斷。
解題方法
先將較小的陣列存入雜湊集合,再掃描另一個陣列。
演算法步驟
- 將陣列 的所有元素放入雜湊集合 。
- 建立空集合 ,用來儲存共同元素。
- 逐一掃描陣列 :
- 若 存在於 中,代表它同時出現在 與 。
- 將 加入 。
- 輸出 。
其中 使用集合結構,可避免同一共同元素因為在 中重複出現而被輸出多次。
虛擬碼
CommonElements(x, y):
H ← empty hash set
R ← empty hash set
for each element a in x:
insert a into H
for each element b in y:
if b is in H:
insert b into R
return R
為降低額外空間,實作時可先選擇較小的陣列建立雜湊集合:
CommonElements(x, y):
if m > n:
swap(x, y)
H ← elements of x
R ← empty hash set
for each element b in y:
if b is in H:
insert b into R
return R
正確性說明
對於任意輸出的元素 :
- 被放入 的條件是 存在於 中;
- 包含陣列 的所有元素;
- 同時來自陣列 的掃描結果。
因此:
所以每個輸出元素必然是共同元素。
另一方面,若 同時存在於 與 :
- 因為 ,所以 已被放入 ;
- 因為 ,掃描到 時會在 中查找成功;
- 因此 會被加入 。
第 4 題15 分
Assume that in a social network, there exist 100000 persons and 1000000 direct friendships connecting these people. Please propose an efficient data structure and an algorithm to determine if A and B are friends.
登入後即可作答並保存紀錄。
核心觀念
本題考查圖論中的「社交網路表示法」與邊的查詢。
將每一個人視為一個頂點(vertex),將兩人之間的直接友誼視為一條邊(edge)。由於朋友關係通常具有對稱性,若 是 的朋友,則 也是 的朋友,因此此社交網路可表示為無向圖:
其中:
題目要判斷的是:圖中是否存在直接連接頂點 與頂點 的邊。
解題方法
採用「雜湊表搭配鄰接串列」表示圖。
對每一個人 ,建立一個集合 friends[u],存放所有與 有直接友誼的人。
若 與 是朋友,則加入:
由於友誼是雙向的,也必須同時加入:
建立資料結構的流程如下:
- 建立 個空的雜湊集合。
- 逐一讀取每條友誼邊 。
- 將 加入
friends[u]。 - 將 加入
friends[v]。
查詢 與 是否為直接朋友時,只需檢查:
關鍵程式碼
#include <unordered_set>
#include <vector>
using namespace std;
const int N = 100000;
vector<unordered_set<int>> friends(N);
void addFriendship(int A, int B) {
friends[A].insert(B);
friends[B].insert(A);
}
bool areFriends(int A, int B) {
return friends[A].find(B) != friends[A].end();
}
areFriends(A, B) 使用雜湊表查詢,因此平均時間複雜度為:
複雜度分析
建立資料結構
共有 條友誼,每條邊加入兩次,因此平均建立時間為:
查詢時間
使用雜湊集合查詢:
這是平均複雜度;在雜湊碰撞嚴重時,最壞情況可能退化,但實務上可透過良好雜湊函數與適當容量配置維持常數時間。
空間複雜度
每條無向邊在兩個鄰接集合中各儲存一次,因此總儲存量為:
本題約需儲存 個頂點及 個鄰接項目,遠小於鄰接矩陣所需的空間。
第 5 題7 分
Given a sequence of data in the order from left to right: D, B, X, I, C, J, L, A, Z
(a) Construct the binary search tree step-by-step.
(b) Continued from (a), construct the AVL tree step-by-step.
登入後即可作答並保存紀錄。
(a) 建立二元搜尋樹(Binary Search Tree, BST)
依序插入資料:D, B, X, I, C, J, L, A, Z,規則為較小值放左子樹,較大值放右子樹:
- 插入 D:作為根節點 。
- 插入 B:,插入至 的左子節點。
- 插入 X:,插入至 的右子節點。
- 插入 I: 且 ,插入至 的左子節點。
- 插入 C: 且 ,插入至 的右子節點。
- 插入 J:、 且 ,插入至 的右子節點。
- 插入 L:、、 且 ,插入至 的右子節點。
- 插入 A: 且 ,插入至 的左子節點。
- 插入 Z: 且 ,插入至 的右子節點。
(b) 建立 AVL 樹(AVL Tree)
AVL 樹要求每個節點的平衡因子()滿足 。
-
插入 D, B, X:樹結構平衡。
D / \ B X -
插入 I:
- 節點 之 ,發生 RL 型不平衡。
- 對 執行 RL 旋轉(先對 右旋,再對 左旋)。
I / \ D X / B
第 6 題16 分
In the following pseudocode program segments, which value of n is printed?
(a)
n := 0
for i := 1 to 10 do
for j := 1 to i-1 do
for k := 1 to j-1 do
for m := 1 to k-1 do
n := n + 1
print n
(b)
n := 0
for i := 1 to 10 do
for j := 1 to i-1 do
for k := 1 to j-1 do
n := n + 1
print n
(c)
n := 0
for i := 1 to 10 do
for j := 1 to 10 do
for k := 1 to 10 do
for m := 1 to 10 do
if i ≠ j and k ≠ m then
n := n + 1
print n
(d)
n := 0
for i := 1 to 10 do
for j := 1 to i do
for k := 1 to j do
for m := 1 to k do
if i=2 x j or j=2 x k or k=2 x m then
n := n + 1
print n
登入後即可作答並保存紀錄。
核心觀念
本題考查巢狀迴圈的執行次數,以及以下計數方法:
- 嚴格遞增索引的組合計數
- 獨立條件的乘法原理
- 容斥原理
- 三角形數公式
若索引滿足
其可能組合數為
(a)
程式中的條件為:
每執行一次 n := n + 1,就相當於從 到 中選出四個數,並依序指定為
因此執行次數為
因此:
時間複雜度為 ;若上限改為一般的 ,則為 。空間複雜度為 。
(b)
此處的索引關係為:
每次累加相當於從 到 中選出三個數,並依序排列成
因此執行次數為
因此:
也可直接逐層計算:
時間複雜度為 ;一般上限為 時,時間複雜度為 。空間複雜度為 。
(c)
四個變數各自從 到 :
條件為:
先計算 的選法:
- 有 種選法;
- 必須不同於 ,因此有 種選法。
所以:
同理, 的選法為:
兩組變數彼此獨立,因此總執行次數為:
因此:
時間複雜度為 ;一般上限為 時,為 。空間複雜度為 。
(d)
迴圈範圍為:
累加條件為三個事件的聯集:
因此使用容斥原理:
計算
由 且 ,可知 。
固定 後, 滿足
共有
種。
因此: