110 高普考高考三級 資訊處理 資料結構 考古題詳解
第 一 題25 分
為 矩陣、 為 矩陣、 為 矩陣、 為 矩陣、 為 矩陣。
(一) 請列出此 5 個矩陣相乘 所有可能的乘法順序(請用括號表示乘法順序)。(5 分)
(二) 請使用 Dynamic Programming(動態規劃)的技巧,計算出此五個矩陣相乘 的最佳乘法順序(請用括號表示乘法順序),使得五個矩陣相乘所需要花費的乘法數量最少。(15 分)
(三) 請列出此五個矩陣相乘所需要花費的最少乘法數量。(5 分)
注意:未說明 Dynamic Programming 的計算過程,不予計分。
登入後即可作答並保存紀錄。
核心觀念
本題考「矩陣鏈乘法」(Matrix-Chain Multiplication)。矩陣乘法具有結合律,因此 可以有多種加括號方式;只要不改變矩陣的先後順序,乘積結果相同,但所需的純量乘法次數可能不同。
若矩陣 的大小為 ,則相乘 時,令 表示所需的最少純量乘法次數,可用下列動態規劃遞迴式計算:
其中 表示最後一次乘法的切割位置; 是將左側結果與右側結果相乘的成本。
本題的維度序列為:
解題方法
由只有一個矩陣的子鏈開始,依序計算長度為 2、3、4、5 的子鏈。每一格都列出不同切割位置的成本,再取最小值;最後依各子鏈的最佳切割位置還原括號順序。
(一)所有可能的乘法順序
五個矩陣保持原順序,加括號方式共有 種:
- )
以上共 種,亦即五個矩陣的加括號方式數量為 Catalan 數 。
(二)動態規劃計算最佳乘法順序
子鏈長度為 2:
子鏈長度為 3:
最佳順序為 。
第 二 題25 分
假設收銀機內銅板的集合為 ,而預計找錢給顧客的金額為 。
(一) 請設計一個 Greedy(貪婪)的演算法,來解決找錢給顧客的問題,使得找給顧客金額 所使用的銅板數量最少,並依此 Greedy 演算法列出找給顧客金額 的過程。(15 分)
(二) 此 Greedy 演算法適合使用何種資料結構來完成。(5 分)
(三) 此 Greedy 演算法的解法是否能保證為最佳解?請舉例說明。(5 分)
登入後即可作答並保存紀錄。
核心觀念
本題考查硬幣找零的 Greedy(貪婪)策略:每一步都從尚未使用的硬幣中,選擇面額不大於剩餘金額的最大硬幣,直到找足 。硬幣面額若有重複,仍視為不同枚硬幣,使用後就移除。
貪婪策略每一步都做局部最佳選擇;但局部最佳不一定能導致硬幣總數最少,因此是否得到最佳解,須視硬幣面額組合而定。
解題方法與找零過程
將硬幣按面額由大到小排列,每次取不超過剩餘金額的最大面額。題目中硬幣為 ,找零金額 。
- 剩餘 :取 ,剩餘 。
- 剩餘 :取一枚 ,剩餘 。
- 剩餘 : 都不超過 的最大面額為 ,取兩枚 ,剩餘 。
- 剩餘 :取一枚 ,剩餘 。
因此 Greedy 找零為:
共使用 枚硬幣。
Greedy-Change(S, W):
將 S 依面額由大到小排序
result ← 空集合
remaining ← W
依序檢查每一枚硬幣 c:
當 c ≤ remaining:
將 c 加入 result
remaining ← remaining - c
若 remaining = 0:
回傳 result
若 remaining > 0:
回報無法找足金額
適用的資料結構
第 三 題25 分
二元搜尋法(binary search)使用 divide-and-conquer(分而治之)演算法技巧,對一個已排序的(sorted)且長度為 的陣列 ,以二元化方式進行資料值 的搜尋,其最差時間複雜度(worst case time complexity)可降到 。
(一) 請使用 C++ 或 Python 語言,修改此二元搜尋法,使其能對未排序的(unsorted)且長度為 的陣列 ,進行三元化搜尋,即以 divide-and-conquer 技巧將此陣列切成三個子陣列,並在可能包含資料值 的子陣列繼續進行 divide-and-conquer 技巧的搜尋;如果找到則回傳 1,如果找不到則回傳 0。(17 分)
注意:請寫一個 searching 類別,內含一個 search 功能。
(二) 請分析修改後的三元化搜尋法其最差時間複雜度(worst case time complexity),以 order 的方式表示。(8 分)
注意:不可將此陣列數值進行排序,請加註解說明程式碼作法。
登入後即可作答並保存紀錄。
核心觀念
二元搜尋法能排除一半搜尋範圍,依賴陣列已排序:比較中間值後,才能判定目標在左半或右半。題目要求陣列維持未排序,因此不能只靠索引位置排除區段。
改以三個子陣列分治時,必須遞迴搜尋三個子陣列,因為任何一個都可能包含 。三分法在此不會減少總搜尋工作量,只改變每次遞迴的切分方式。
解題方法
使用半開區間 表示目前搜尋範圍,長度為 。將區間切成三段:
其中 ,。程式先檢查目前區間的元素是否等於 ;若否,便遞迴搜尋三段。當區間為空時,表示沒有找到。
程式碼
第 四 題25 分
(一) 請使用 C 語言寫一副程式:
對一個未排序的(unsorted)且長度為 的陣列 ,尋找陣列中的中位數與平均數,並分別存入 及 ,分析其運算複雜度。(17 分)
(二) 請舉例說明此副程式最差情況(worst case)所花費的運算複雜度。(8 分)
注意:請加註解說明程式碼作法。
登入後即可作答並保存紀錄。
核心觀念
本題考查中位數、算術平均數的定義,以及未排序陣列的選取(selection)與時間複雜度分析。
- 中位數:將數值依大小排序後,位於中央的數值。若 為奇數,取第 小的數;若 為偶數,取第 小與第 小兩數的平均。
- 算術平均數:所有元素總和除以元素個數,即 。
- 選取(selection):在未排序資料中,找出第 小的元素。若採用最差時間為 的選取演算法,中位數可在線性時間內求得;若先排序再取中間元素,則需要 。
題目指定 int *mean 與 int *average,以下依常見考題假設,將中位數及平均數以整數回傳;偶數筆資料的中位數與平均數採整數除法,會捨去小數部分。
解題方法
先複製陣列,避免尋找中位數時改動呼叫端的原始資料。對複本使用 median-of-medians(中位數的中位數) 選取演算法,取得所需順位的元素;其最差時間複雜度為 。
- 若 為奇數,選出第 小的元素。
- 若 為偶數,分別選出第 小與第 小的元素,取其整數平均。
平均數則以一次走訪累加所有元素,最後除以 。總時間仍為 ,空間需求為 ,主要用於保存選取演算法所操作的複本。