112 專技高考高等考試 資訊技師 程式設計 考古題詳解
第 一 題20 分
使用 C++ 或 Java 設計一個函式(function、method),傳入一個大於或等於 的整數,可以列出輸入之整數的質因數乘積。
注意:符號 ^ 代表次方。
執行範例:
輸出:
輸出:
輸出:
登入後即可作答並保存紀錄。
核心觀念
本題考查質因數分解與迴圈設計。質因數是本身為質數的因數;依算術基本定理,每個大於 的整數都能唯一表示為質數的乘積。
例如:
題目範例也要求輸出沒有質因數重複時的格式,例如 。輸入為質數時,另依題目指定格式輸出 ,例如 。
解題方法
由最小可能的質因數 開始,逐一測試整數 是否能整除目前尚未分解的數 :
- 若 能整除 ,就持續除以 ,並計算其出現次數。
- 若 出現一次以上,將質因數與次方輸出;次方為 時省略
^1。 - 當 不再能整除 ,繼續測試下一個整數。
- 測試至 時,若 ,剩下的 必為質數,直接輸出。
只需測試到平方根,是因為合數必有一個不大於其平方根的因數。若一直沒有找到這樣的因數,剩下的數便是質數。
C++ 參考程式
第 二 題20 分
一個骰子共有六面,點數分別為 。遊戲時擲出三個骰子,若三個骰子的點數相同,則分數為三個骰子點數總和再乘以 ;若其中有兩個骰子點數相同,另一個不同,則分數為點數不同骰子的點數。若三個骰子的點數都不同,則重新再擲三個骰子,直到出現有分數的情況為止。請使用物件導向程式語言 C++ 或 Java 為此遊戲設計程式。
執行範例一:
骰子點數:、、;得分:
執行範例二:
骰子點數:、、;得分:
執行範例三:
骰子點數:、、;重擲
骰子點數:、、;重擲
骰子點數:、、;得分:
登入後即可作答並保存紀錄。
核心觀念
本題考查物件導向程式設計中的條件判斷、迴圈控制與亂數產生。每次擲出三個骰子後,依點數相同的情形決定得分:
- 三個點數相同:得分為三顆骰子點數總和再乘以 。
- 恰有兩個點數相同:得分為那顆點數不同的骰子的點數。
- 三個點數都不同:本次沒有得分,重新擲骰,直到出現前兩種情形。
解題方法
將三顆骰子的點數存入陣列,每次擲骰後先輸出點數,再按照下列順序判斷:
- 若三個點數相同,計算 ,輸出得分並結束。
- 若恰有一組點數相同,找出與另外兩顆不同的點數,將該點數作為得分。
- 否則三個點數皆不同,輸出「重擲」,進入下一次迴圈。
判斷順序先檢查三個點數是否全相同,再檢查兩個點數是否相同,可清楚區分兩種得分情形。
C++ 程式
第 三 題40 分
二元搜尋樹(binary search tree)是一種資料經過整理後的二元樹。對於任何一個節點,若左子樹(left subtree)存在,則左子樹所有節點的值均小於自己的值;若右子樹(right subtree)存在,則右子樹所有節點的值均大於自己的值。
請用 C++ 或 Java 寫一個二元搜尋樹的類別(class),包括新增一個節點(insert)、刪除一個節點(remove)以及中序走訪(inorder)這三個函式(function),並撰寫主程式完成以下工作:
- 依序新增 、、、、 到一個空的二元搜尋樹。
- 以中序走訪此樹。
- 刪除 。
- 增加 。
- 以中序走訪此樹。
登入後即可作答並保存紀錄。
核心觀念
二元搜尋樹(Binary Search Tree, BST)遵守以下規則:對每個節點,左子樹所有值都小於節點值,右子樹所有值都大於節點值。本題不插入重複值。
BST 的中序走訪順序為「左子樹、根節點、右子樹」,因此走訪結果會由小到大排列。
刪除節點時分三種情況:
- 沒有子節點:直接刪除。
- 只有一個子節點:以子節點取代被刪除的節點。
- 有兩個子節點:以其中序後繼(右子樹的最小值)或中序前驅(左子樹的最大值)取代,再刪除該後繼或前驅的原節點。
解題方法
依序插入 、、、、:
- 成為根節點。
- ,插入 的左側。
- ,往左比較;,插入 的右側。
- ,插入 的右側。
- ,往右比較;,插入 的右側。
所得結構如下:
25
/ \
15 30
\ \
20 40
中序走訪依序為 。
刪除 時,節點 只有右子節點 ,因此以 取代 :
25
/ \
15 40
\
20
再插入 : 且 ,因此插入 的左側:
25
/ \
15 40
\ /
20 30
再次中序走訪仍為 。
C++ 程式
第 四 題20 分
請寫出下列 Java 語言程式的執行結果,也就是下列兩個敘述的輸出結果:
System.out.println("Sum before the swap: " + Element.sum(e));
System.out.println("Sum after the swap: " + Element.sum(e));
Trace.java:
public class Trace{ public static void main(String[] args){ Element[] e = new Element[5]; e[0] = new Element(10); e[1] = new Element(5); e[2] = e[1]; e[3] = e[0]; e[4] = new Element(5); System.out.println("Sum before the swap: " + Element.sum(e)); for(int i = 0; i < e.length - 1; i++){ if(e[i] == e[i+1]){ break; } else{ Element eTmp = e[i]; e[i] = e[i+1]; e[i+1] = eTmp; } } System.out.println("Sum after the swap: " + Element.sum(e)); } }
Element.java:
public class Element{ private int value;
public Element(int value){
this.value = value;
}
public int getValue(){
return value;
}
public static int sum(Element [] e){
int sum = e[0].getValue();
for(int i = 0; i < e.length - 1; i++){
if(e[i].getValue() <= e[i+1].getValue()){
continue;
}
sum += e[i+1].getValue();
}
return sum;
}
}
執行結果:
Sum before the swap: 20
Sum after the swap: 10
登入後即可作答並保存紀錄。
核心觀念
本題考兩個 Java 觀念:
- 陣列元素可以指向同一個物件:
e[1] = e[2]這類指定會複製參考,不會建立新物件。判斷e[i] == e[i+1]時,==比較的是兩者是否參考同一個物件。 - 交換陣列元素只改變參考位置:透過暫存變數交換
e[i]與e[i+1],不會修改物件內的value。 Element.sum(e)不是一般的陣列總和:每次比較相鄰元素,只有當前一個值大於下一個值時,才把下一個值加進總和。
解題方法
先以物件代號標示陣列中的參考:
| 索引 | 參考 | value |
|---|---|---|
e[0] | A | 10 |
e[1] | B | 5 |
e[2] | B | 5 |
e[3] | A | 10 |
e[4] | C | 5 |
其中 e[2] = e[1],所以兩者都指向 B;e[3] = e[0],所以兩者都指向 A。C 則是另一個值為 5 的物件。
交換前計算總和
sum 初值為 e[0].getValue,即 。逐一檢查相鄰值:
| 相鄰索引 | 比較 | 動作 | 總和 |
|---|---|---|---|
0, 1 | 為否 | 加入 e[1] 的值 5 | 15 |
1, 2 | 為是 | continue,不加值 | 15 |
2, 3 | 為是 | continue,不加值 | 15 |
3, 4 | 為否 | 加入 e[4] 的值 5 | 20 |
因此交換前輸出:
Sum before the swap: 20