W05|先記住目前冠軍:最大值與最小值
今天完成後,我可以
- 每讀入一筆資料,就判斷是否需要更新目前的最大值或最小值。
- 根據題目條件,選擇第一筆真實資料或範圍外數值作為起始值。
- 找到極值時,也能同步記錄它的位置或其他相關資訊。
本週練習極值的更新過程,不使用max()、min()、sorted()、sort()或串列保存全部資料。
一、教師示範與課中跟做
1-1|b019 誰是學霸(50分)
題目會逐行輸入全班成績,請找出最高分。先看題目的輸入與輸出,再跟著教師一起解題。
開始前先想一想:如果班上只有3位同學,你會怎麼找最高分?如果變成40位,原來的方法還適合嗎?
看教師示範時,只要追蹤四個問題:
max_score現在保存的是什麼?max_score的初始值應該設定為多少?這個值從哪裡來?- 第一筆已經讀入後,迴圈應執行
n次還是n - 1次? - 讀到更高成績時,應該寫
max_score = score還是相反?
示範結束後,請關閉示範畫面,自己重新輸入、測試並提交。本題不使用串列、max()或排序功能。
需要時展開:挖空程式碼骨架
四個空格分別在處理:初始值、迴圈範圍、比較條件與更新動作。請先說明每一格的任務,再填入程式碼。
解完b019再整理:這題用到的三個觀念
- 每讀到一筆新成績,就讓它挑戰「目前最高分」。
- 第一筆已先成為目前最高分,所以後面只剩
n - 1筆。 - 要更新紀錄時,把新成績放進
max_score;等號方向不能寫反。
處理完每一筆資料後,max_score都應代表「目前已看過成績中的最高分」。
延伸思考:迴圈裡的數字能不能代表座號?
第一位同學的成績已經先讀入,因此剩下要處理的是第2位到第n位同學:
請觀察:student_number第一次與最後一次分別是多少?它們各代表哪一位同學?
b019只要求最高分,所以暫時不需要使用這個座號。如果下一題還要回答「最高分是第幾位同學」,這個變數可以怎麼幫忙?
二、課中獨立練習
2-1|b024 低空飛過(50分)
這題不是從全部成績找最低分,而是只從及格成績中尋找。
題目中的成績範圍是0~100。因為101不可能是真正成績,可以先把它當成「目前還沒有找到及格者」的暫時記號。
這和b019的初始化方式不同:
- 每筆資料都有資格參加比較:可以先使用第一筆真實資料。
- 只有部分資料符合資格,而且可能完全找不到:可以根據題目範圍選擇一個不可能成為答案的值。
處理每筆成績時,分成兩個問題思考:
- 這筆成績是否及格?
- 及格後,它是否比目前最低及格分更低?
初次撰寫時,可以先使用兩層if表達「先取得資格,再挑戰紀錄」,不用急著把兩個條件合併。
縮排形狀可以先寫成:
if 第一個條件:
if 第二個條件:
要做的事
提示一:利用範圍外的暫時記號
先將目前最低及格分設為101。第一筆及格成績一定小於101,因此會自然取代暫時記號。
提示二:最後如何知道沒有人及格?
全部成績處理完成後,如果目前最低及格分仍是101,表示沒有任何及格成績,應依題意輸出QQ。
補救練習:如果基本最小值更新還不熟
可以先完成a377精打細算,再回來訂正b024。這是需要時使用的補救題,不是本週正式課後作業。
三、解題後整理
極值不只是一個數字
有些題目除了極值,還會問極值出現在哪個座號。找到更好的資料時,極值與座號必須一起更新,否則可能得到「正確的最高分,卻配上錯誤的座號」。
迴圈變數不一定叫i
如果迴圈只負責重複固定次數,可以使用i。如果迴圈中的數字代表座號、天數或年份,就改用student_number、day或year等能說明身分的名稱。
四、課後挑戰
| 題目 | 配分 | 定位 | 本週目標 |
|---|---|---|---|
b021 誰是學霸之到底是誰 |
40分 | 核心應用 | 找最大值時同步記錄座號,並保留較早的最高分者 |
a102 叢林小松鼠2 |
30分 | 選做挑戰一 | 不排序、不保存全部資料,嘗試維護目前前三大值 |
c071 遊戲選角 |
30分 | 選做挑戰二(APCS) | 找第二大的能力值,並保留該角色的攻擊力與防禦力 |
4-1|b021 誰是學霸之到底是誰(40分)
已知成績範圍為0~100,可以用-1表示「目前還沒有最高分」。這次迴圈中的數字就是學生座號,因此使用student_number會比i更容易閱讀。
提示:分數與座號要一起更新
題目要求同分時保留座號較小者,因此請思考比較時應使用>還是>=。
完成後整理:同分時要留下誰?
如果只在新成績>目前最高分時更新,同分時不更新,會保留較早出現者;如果使用>=,同分時也會更新,最後會留下較晚出現者。
這不是固定背誦規則;仍要先讀清楚題目要求留下最早或最晚出現者。
4-2|a102 叢林小松鼠2(選做,30分)
這次要選出前三重的果實並計算總重量。可以準備三個變數,分別保存目前第一大、第二大與第三大。
最大的挑戰不是比較,而是更新順序:當新的第一大出現時,原本的第一大與第二大應該移到哪裡?
新的第一大出現
→ 原本第二大移到第三大
→ 原本第一大移到第二大
→ 新資料放入第一大
為什麼移動時要從第三名的位置開始處理,而不能先覆蓋第一名?請用三個不同數字追蹤一次再開始寫程式。
本題是進階選做,不列入本週基本完成要求。
4-3|c071 遊戲選角(APCS選做,30分)
完成a102後再挑戰這題。每位角色的比較依據不是單一輸入值,而是由攻擊力與防禦力算出的能力值;最後輸出的卻是該角色原本的攻擊力與防禦力。
先以只有三位角色的情況思考:除了記住目前第一大與第二大的能力值,哪些原始資料也必須跟著移動?
本題的60%子題只有三位角色。即使暫時無法完成一般情況,也可以先完成這個版本。
每行的攻擊力與防禦力是兩個以空白分隔的數字,可查閱輸入輸出技巧|同一行有固定數量的資料;輸出兩個數字時可查閱同一行使用空白分隔。能力值的平方可使用**。
五、完成後自我檢查
- 我能說明極值變數在每一圈結束時代表什麼。
- 全部資料都能參賽時,我使用第一筆資料作為初始極值,後續迴圈執行
n - 1次。 - 我知道最大值與最小值的比較方向不同。
- 我只在新資料更好時才更新目前答案。
- 題目要求位置時,我會把極值和位置一起更新。
- 題目要求第二大或前三大時,我會先畫出資料移動順序,再開始賦值。
- 我有依同分規則選擇
>或>=。 - 我知道全部資料都能參賽時,優先使用第一筆真實資料初始化。
- 我只在題目提供明確範圍且可能沒有符合資料時,使用範圍外的暫時記號。
- 我沒有使用
max()、min()、排序或串列跳過本週練習。 - 我測試過極值在第一筆、最後一筆、重複出現及全部相同的情況。
六、超前挑戰題單
本區自由選做,不計入W05課中或課後配分,也不需要全部完成。請先完成本週正式題目,再從感興趣的題目選一題挑戰;如果暫時卡住,可以把問題記下來,之後學到更多工具再回來完成。
開始挑戰前:先將隨堂練習交卷
JMJ進行隨堂練習時,不能直接前往練習以外的題目。完成本週必做題後,請依照下列順序操作:
- 確認必做題都已經送出,並檢查目前得到的分數。
- 回到這次隨堂練習的「題目列表」,向下捲到題目下方。
- 依老師指示,按下左下角綠色的「做完交卷(交卷之後將無法再進入)」按鈕。
- 確認完成交卷後,再回到本頁點選下方題名;題目會在新的分頁開啟。
注意:按下「做完交卷」後就無法再次進入這份隨堂練習。還想繼續修改必做題時,不要提早交卷;不確定時先詢問老師。
| 建議順序 | 題目 | 可以練到什麼 | 挑戰限制 |
|---|---|---|---|
| 1 | a071 這就是我們之間的差距! |
同時維護最大值與最小值,再計算兩者差距 | 不使用max()、min()、排序或串列 |
| 2 | a148 捕魚(Fishing) |
找最接近的目標,並讓座標與目前最佳值一起更新 | 不使用串列與min();可以比較距離的平方 |
| 3 | a064 最大公因數 |
用窮舉、取餘數與變數更新保留最後一個共同因數 | 不使用math.gcd() |
| 4 | a040 文文的求婚(三) |
複合條件、範圍迴圈與計數 | 逐年判斷,不直接套用閏年數量公式 |
| 5 | a150 躲避球(Dodgeball) |
依事件逐步更新目前狀態 | 每處理一筆事件,就立即更新一次結果 |
| 6 | a149 計程車(Taxi) |
把較長的規則拆成條件、計算與加總 | 先分段列出規則,再開始寫程式 |
完成一題後,請確認自己能不看別人的程式,說明「每個變數保存什麼」以及「每一圈做了什麼」。
