巢狀迴圈:迴圈裡面再套一個迴圈
你已經學會三種迴圈工具了:for(跑 N 次)、while(跑到條件不成立)、break/continue(中途控制)。聽起來很完整對吧?
但這個世界有一種問題,單靠一層迴圈解決不了。
為什麼用「逐排貼標籤」來比喻?因為巢狀迴圈的結構跟這個任務完全一樣:都有兩個層次的重複,外層管「哪一排」,內層管「這排裡的每個位子」。想像一下:你是學校的管理員,要幫每排座位貼標籤。教室有 5 排,每排有 6 個座位。你的工作是走到「第 1 排」,然後逐一貼 6 個座位的標籤;貼完第 1 排之後,走到第 2 排,再貼 6 個;依此類推,直到第 5 排貼完為止。
這個任務有兩個層次的重複:「逐排重複」和「每排內逐座位重複」。用一個 for 迴圈只能處理一個層次的重複,處理不了這種「重複裡面還有重複」的結構。
這就是今天要教的巢狀迴圈(Nested Loop)。聽起來有點可怕嗎? ʅ(´◔౪◔)ʃ 其實就是「for 裡面再加一個 for」,五分鐘你就會了。

📷 圖 9:學生要在教室每排每個座位貼標籤的四格漫畫(AI 製圖)
💡 📋 學習目標
看完這一節,希望你將能夠:
- 寫出雙重
for迴圈,理解外層控制列、內層控制行的執行順序 - 用巢狀迴圈印出直角三角形、長方形、九九乘法表
- 在巢狀迴圈中結合
if條件,找出符合條件的數字對 - 培養對巢狀迴圈效能的直覺:外層跑 N 次 × 內層跑 M 次 = 總共 N×M 次
- 完成 Judge 解題:直角三角形圖案 + 九九乘法表
知識點 A:雙重 for 迴圈基礎
為什麼需要巢狀迴圈?
先思考一個問題:你想用 for 迴圈列印下面這個圖案:
*
**
***
****
*****第 1 行印 1 個星號,第 2 行印 2 個,……第 5 行印 5 個。這很像「每行的工作量不同」。
你可以用字串乘法解決這個特定問題:print("*" * i)。但如果印的不是重複的字元,而是要「逐格計算」呢?比方說九九乘法表,每一格的值是 i * j,沒辦法靠字串乘法搞定。這時候你就需要一個「負責每一行的迴圈」:它本身也是迴圈。
為了解釋清楚這個結構,讓我先用一個日常生活的比喻。
你去電影院買票,服務員要幫所有座位做點名。電影院有 3 排,每排 4 個座位。服務員的工作流程是:先進第 1 排,喊 1-1、1-2、1-3、1-4;喊完第 1 排後,進第 2 排,喊 2-1、2-2……以此類推。這個流程有兩層:「逐排循環」(外層)和「每排內逐座位循環」(內層)。
Python 的雙重 for 迴圈,就是在模擬這個流程。讓我們看程式碼。
雙重 for 迴圈的基本語法
先從最簡單的例子開始,讓 Python 印出 3 排 × 4 格的座位編號:
for row in range(1, 4): # 外層:row = 1, 2, 3
for col in range(1, 5): # 內層:col = 1, 2, 3, 4
print(row, col)輸出結果:
1 1
1 2
1 3
1 4
2 1
2 2
...
3 4這就是巢狀迴圈的核心概念:外層迴圈每跑一次,內層迴圈就完整跑一遍。
來看 Trace Table,追蹤每一步的變數值:
外層 row | 內層 col | 輸出 |
|---|---|---|
| 1 | 1 | 1 1 |
| 1 | 2 | 1 2 |
| 1 | 3 | 1 3 |
| 1 | 4 | 1 4 |
| 2 | 1 | 2 1 |
| 2 | 2 | 2 2 |
| 2 | 3 | 2 3 |
| 2 | 4 | 2 4 |
| 3 | 1 | 3 1 |
| 3 | 2 | 3 2 |
| 3 | 3 | 3 3 |
| 3 | 4 | 3 4 |
外層 row 跑了 3 次,每次外層 row 前進一格,內層 col 就從頭跑到尾(1→2→3→4)。總共輸出 3 × 4 = 12 行。
直角三角形圖案
學會基本語法後,來印第一個圖案:直角三角形。目標是輸入 N = 4,印出:
*
**
***
****思考一下:第 i 行要印幾個星號?答案是 i 個。用雙重迴圈,外層控制「第幾行」,內層控制「這行印幾個星號」。程式碼如下:
n = int(input())
for i in range(1, n + 1): # 外層:i = 1, 2, ..., n(第 i 行)
for j in range(1, i + 1): # 內層:跑 i 次(印 i 個星號)
print("*", end="") # end="" 讓星號在同一行
print() # 每行結尾換行`print("*", end="")`
print() 預設每次都會換行。end="" 讓它改用空字串結尾,也就是不換行。等內層迴圈跑完,外層再呼叫一次沒有參數的 print() 來換行。
Trace Table(以 N = 3 為例):
外層 i | 內層 j | 動作 |
|---|---|---|
| 1 | 1 | 印 *,不換行 |
| 1 | (內層結束) | 換行 → 第 1 行:* |
| 2 | 1 | 印 *,不換行 |
| 2 | 2 | 印 *,不換行 |
| 2 | (內層結束) | 換行 → 第 2 行:** |
| 3 | 1 | 印 *,不換行 |
| 3 | 2 | 印 *,不換行 |
| 3 | 3 | 印 *,不換行 |
| 3 | (內層結束) | 換行 → 第 3 行:*** |
對了!外層 i 決定「這行長度」,內層 j 負責「逐個印出星號」。你可以把外層想成「管理者」,內層想成「執行者」(ฅ'ω'ฅ)
長方形圖案
有了直角三角形,再來一個稍微不同的例子。長方形:每行都有固定數量的星號。輸入兩個數字 R 和 C,印出 R 行、每行 C 個星號。
r = int(input())
c = int(input())
for i in range(r): # 外層:控制行數(共 r 行)
for j in range(c): # 內層:每行印 c 個星號
print("*", end="")
print()長方形跟三角形的差別:三角形的內層範圍隨著 i 改變(range(1, i+1)),長方形的內層範圍固定(range(c))。
九九乘法表
現在挑戰稍難一點的:九九乘法表。目標是讓每一格顯示 i * j 的值,格式對齊(每格佔 4 個字元)。在貼程式碼之前,先補兩個會用到的小知識:跳脫字元 \t 跟 f-string,看完馬上就用得到。
📌 `\t` 是什麼?跳脫字元(Escape Character)入門
\t 在 Python 字串裡代表 Tab 鍵(定位字元,Tab Character)。當你輸出 "\t",游標會跳到下一個定位點(Tab Stop),這就是表格類輸出能排得整齊的祕密。
字串裡用反斜線 \ 開頭的特殊符號,有個專有名詞叫跳脫字元(Escape Character)。常見的有:
\n:換行(newline)\t:Tab(tab)\\:反斜線本身(避免被當成跳脫字元的開頭)
舉個例子:
print("a\tb") # 輸出:a b(中間是一段 Tab 距離)
print("a\nb") # 輸出:a 換行 b雖然在原始碼裡你看到 \t 是「反斜線」加「t」兩個符號,但 Python 讀字串時會把它合併處理成一個 Tab 字元,不是真的印出 \ 跟 t (´・ω・`)
📌 f-string 是什麼?字串裡塞變數的便捷寫法
還記得 1-2「類題一:段考成績平均」的提示中偷學過 f"{result:.1f}" 嗎?現在正式介紹這個寫法。
在字串前面加 f(例如 f"Hello, {name}"),大括號 { ... } 裡面可以放變數或運算式,Python 會把它計算後嵌進字串:
name = "小明"
print(f"Hello, {name}") # 輸出:Hello, 小明
a = 7
b = 6
print(f"{a} × {b} = {a * b}") # 輸出:7 × 6 = 42大括號裡還能加「格式說明」:f"{value:N}" 中的 :N 代表「這個值至少佔 N 個字元寬,不夠寬就在前面補空白(預設右對齊)」。例如:
f"{7:4}"→" 7"(前面補 3 個空白,總寬 4)f"{42:4}"→" 42"(前面補 2 個空白,總寬 4)f"{1234:4}"→"1234"(剛好 4 格,不補)
這就是讓表格欄位對齊的常見手法,九九乘法表馬上就會用到 ᕕ( ᐛ )ᕗ
兩個小知識搞定,回來看九九乘法表的程式碼:
for i in range(1, 10): # 外層:i = 1 到 9
for j in range(1, 10): # 內層:j = 1 到 9
print(i * j, end="\t") # \t 讓數字之間以 Tab 對齊
print() # 每行結尾換行九九乘法表有 9 × 9 = 81 次迭代,Trace Table 只顯示重點部分:
外層 i | 內層 j | 計算 | 輸出 |
|---|---|---|---|
| 1 | 1 | 1×1=1 | 1 (tab) |
| 1 | 2 | 1×2=2 | 2 (tab) |
| 1 | 3 | 1×3=3 | 3 (tab) |
| 1 | ... | ... | ... |
| 1 | 9 | 1×9=9 | 9 → 換行 |
| 2 | 1 | 2×1=2 | 2 (tab) |
| 2 | 2 | 2×2=4 | 4 (tab) |
| ... | ... | ... | ... |
| 9 | 8 | 9×8=72 | 72 (tab) |
| 9 | 9 | 9×9=81 | 81 → 換行 |
九九乘法表,三行程式碼! Σ(゚Д゚)

📷 圖 10:巢狀迴圈執行流程示意圖,外層控制行、內層控制列(AI 製圖)
常見錯誤提醒
⚠️ 縮排錯誤:內層迴圈只跑一次
巢狀迴圈最常見的錯誤是縮排搞錯,讓「應該在外層的語句」跑進了外層,或「應該在內層的語句」跑到了外層。
錯誤示範:
for i in range(1, 4):
for j in range(1, i + 1):
print("*", end="")
print() # ❌ 縮排不夠!print() 跑到最外層,只換行一次正確:
for i in range(1, 4):
for j in range(1, i + 1):
print("*", end="")
print() # ✅ 對齊外層迴圈,每行結尾換行⚠️ 外層與內層變數名稱撞名
for i in range(3):
for i in range(5): # ❌ 外層跟內層都用 i!
print(i)當你用同一個變數名,內層迴圈會覆蓋外層的 i,導致外層迴圈判斷出錯。外層用 i,內層就用 j,是慣例寫法。如果還有第三層,用 k。
知識點 B:巢狀迴圈應用
你現在已經掌握了雙重 for 迴圈的基本語法,能夠處理「行列結構」的問題。但巢狀迴圈的威力不只是印圖案:當你在內層加上 if 條件,或是計算行內的空格數,就能解決更多種類的問題。
接下來,我們把巢狀迴圈跟之前學的 if 條件結合起來,再看一個「需要空格配合」的圖案,最後討論巢狀迴圈的效能直覺。
巢狀迴圈 + 條件判斷:找出符合條件的數字對
有一道典型的計算題:「找出 1 到 N 之間所有滿足 i + j = 10 的整數對 (i, j),其中 i ≤ j。」
思路是:外層控制 i,內層控制 j,然後在內層加 if 判斷。程式碼如下:
n = int(input())
for i in range(1, n + 1): # 外層:i 從 1 到 n
for j in range(i, n + 1): # 內層:j 從 i 開始(確保 i ≤ j)
if i + j == 10: # 條件:兩數之和等於 10
print(i, j)以 N = 10 為例,輸出:
1 9
2 8
3 7
4 6
5 5Trace Table(省略不符合條件的列,只展示觸發 print 的時刻):
外層 i | 內層 j | i+j | 是否等於 10 | 輸出 |
|---|---|---|---|---|
| 1 | 1 | 2 | ✗ | — |
| 1 | ... | ... | ✗ | — |
| 1 | 9 | 10 | ✓ | 1 9 |
| 2 | 2 | 4 | ✗ | — |
| 2 | ... | ... | ✗ | — |
| 2 | 8 | 10 | ✓ | 2 8 |
| ... | ... | ... | ... | ... |
| 5 | 5 | 10 | ✓ | 5 5 |
注意內層從 range(i, n+1) 而不是 range(1, n+1) 開始,這是為了確保 i ≤ j,避免重複計算 (1,9) 和 (9,1) 這種「同一對不同順序」的情況。掌握這個「讓 j 從 i 開始」的技巧,很多計數問題都能迎刃而解 ᕦ(ò_óˇ)ᕤ
等腰三角形:空格 + 星號的計算
等腰三角形比直角三角形難一點,因為每行不只有星號,還有前置空格:
* ← 第 1 行:4 空格 + 1 個星號
*** ← 第 2 行:3 空格 + 3 個星號
***** ← 第 3 行:2 空格 + 5 個星號
******* ← 第 4 行:1 空格 + 7 個星號
********* ← 第 5 行:0 空格 + 9 個星號規律:
- 第
i行有n - i個空格 - 第
i行有2*i - 1個星號
n = int(input())
for i in range(1, n + 1):
# 印空格
for j in range(n - i):
print(" ", end="")
# 印星號
for j in range(2 * i - 1):
print("*", end="")
print() # 換行同一行裡用了兩個不同的內層迴圈,一個負責空格、一個負責星號,但它們都在同一次外層迭代中執行。這是巢狀迴圈常見的模式。

📷 圖 11:電影院服務員逐排逐座位點名的四格漫畫(AI 製圖)
效能直覺:N×M 次
「老師,巢狀迴圈跑幾次?」這個問題很重要,特別是當 N 很大的時候。
答案很直覺:外層跑 N 次,內層跑 M 次,總共 N×M 次。
| 外層次數(N) | 內層次數(M) | 總迭代次數(N×M) |
|---|---|---|
| 3 | 4 | 12 |
| 10 | 10 | 100 |
| 100 | 100 | 10,000 |
| 1,000 | 1,000 | 1,000,000 |
當 N = 1,000 時,雙重迴圈就跑了一百萬次!這在現在的電腦上通常沒問題,但如果 N = 1,000,000,就需要警惕了。這種「操作次數隨輸入大小成正比」的思維,就是演算法複雜度的入門概念,你在 Ch4 學習搜尋和排序時會更深入接觸。
不用死背這個數字
現在只要記得一個口訣:「巢狀迴圈的工作量是兩層的乘積」。遇到 APCS 題目問「這個程式最多跑幾次」,把兩層迴圈的上限乘起來就是答案。
常見錯誤提醒
⚠️ 忘記每行結尾的 `print()` 換行
這是初學者最常犯的錯:只顧內層的輸出,忘記外層結束後要換行。
for i in range(1, 4):
for j in range(1, i + 1):
print("*", end="")
# ❌ 所有星號全部擠在同一行:***記得在外層迴圈的縮排層加上 print()。
⚠️ range 的內外層搞混
n = 5
for i in range(n): # 外層:0 到 n-1
for j in range(i): # 這行到底是「j 跑 0 到 i-1」嗎?先用 Trace Table 把 i = 0, 1, 2 時的 j 值列出來,確認跑的次數是否符合你的預期。不確定就先用小 N(比如 N=3)手動追蹤。
Judge 解題實戰:星星直角三角形
題目說明
輸入一個正整數 N,印出高度為 N 的星號直角三角形:第 1 行印 1 個 *,第 2 行印 2 個 *,……第 N 行印 N 個 *。
輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 20)
輸出格式: 共 N 行,第 i 行有 i 個 *,不含多餘空格
範例一:
| 輸入 | 輸出 |
|---|---|
3 | ****** |
範例二:
| 輸入 | 輸出 |
|---|---|
5 | *************** |
老師的建議
先自己動手寫!回憶一下:外層控制第幾行,內層控制這行印幾個星號。
卡關了再往下看。
Step 1:分析 IPO
- I(Input):讀取正整數 N
- P(Process):外層迴圈從 1 到 N;內層迴圈從 1 到 i,每次印一個
* - O(Output):每行結尾換行
Step 2:寫出程式碼
n = int(input())
for i in range(1, n + 1):
for j in range(1, i + 1):
print("*", end="")
print()Step 3:逐行解讀
n = int(input())— 讀取 Nfor i in range(1, n + 1):— 外層,i 從 1 到 N(控制第幾行)for j in range(1, i + 1):— 內層,j 跑 i 次(印 i 個星號)print("*", end="")— 印一個*,不換行print()— 這行對齊外層,內層跑完後換行
以 N = 3 為例,逐行驗證:
i=1:內層跑 1 次 → 印*→ 換行i=2:內層跑 2 次 → 印**→ 換行i=3:內層跑 3 次 → 印***→ 換行
Step 4:常見錯誤排查
❌
range(1, i + 1)寫成range(i)range(i)從 0 開始,跑 0 到 i-1,共 i 次,印出的數量是對的,但 j 的值是 0 開頭。如果後面需要用到 j 的值(比如印數字),要注意起點。印星號不受影響。❌
print()放在內層迴圈裡(縮排多一格)會變成「每印一個
*就換行」,結果是每行只有一個*,無論 N 是多少。
Judge 解題實戰:九九乘法表
題目說明
讀入一個整數 N(1 ≤ N ≤ 9),印出 1×1 到 N×N 的乘法表。每個數字佔 4 個字元寬(右對齊)。
輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 9)
輸出格式: 共 N 行,第 i 行為 i×1, i×2, …, i×N 的結果,每個數字右對齊佔 4 個字元
範例一(N = 3):
| 輸入 | 輸出 |
|---|---|
3 | 1 2 3 2 4 6 3 6 9 |
範例二(N = 5):
| 輸入 | 輸出 |
|---|---|
5 | 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25 |
老師的建議
關鍵在於「格式對齊」。每個數字要佔 4 個字元寬,試試 f"{i*j:4}"。
Step 1:分析 IPO
- I(Input):讀取 N
- P(Process):外層控制第 i 行(i 從 1 到 N),內層計算
i * j(j 從 1 到 N) - O(Output):每個數字佔 4 個字元,行尾換行
Step 2:寫出程式碼
n = int(input())
for i in range(1, n + 1):
for j in range(1, n + 1):
print(f"{i * j:4}", end="") # :4 讓每個數字右對齊佔 4 格
print()Step 3:逐行解讀
n = int(input())— 讀取 Nfor i in range(1, n + 1):— 外層,i 從 1 到 N(控制列)for j in range(1, n + 1):— 內層,j 從 1 到 N(控制行)print(f"{i * j:4}", end="")— 計算 i×j,印出並右對齊佔 4 格;end=""不換行print()— 內層跑完後換行
格式字串 f"{i * j:4}" 中的 :4 代表「此欄位至少佔 4 個字元,預設右對齊」。數字小的會在前面補空格。
Step 4:常見錯誤排查
❌ 忘記格式對齊,直接用
print(i * j, end="\t")Tab 對齊在小數字時看起來還 OK,但當數字超過一位 tab 停靠點時就會跑掉。建議用
:4格式。❌ 兩個迴圈的上限都用
range(1, 10)而不是range(1, n + 1)這樣 N 的值就沒有意義,永遠印 9×9。記得兩個迴圈的範圍都要跟 N 有關。

📷 圖 12:學生用巢狀迴圈一步步印出乘法表的教學示意圖(AI 製圖)
自己動手試試!
來了!六道題目,從基礎到進階,每道都是 APCS 實際出現過的圖案類型 _(´ཀ`」 ∠)_ 加油!
星號長方形
問題情境:小晴在電腦課的期末設計專題中,想用 * 星號拼出各種幾何圖案來裝飾班級的佈告欄。她的第一個目標是印出一個長方形:老師說只要輸入「幾行、幾列」,程式就要自動產生對應的星號陣列。小晴回想起上學期美術課做過的馬賽克拼貼,那時候她一格一格手動貼磁磚,累得手都痠了。現在學會了迴圈,她終於可以讓電腦幫忙重複這些動作。小晴想了想,決定先搞清楚:「外層要跑幾次?內層每次要做什麼?」只要把這兩件事想清楚,兩層迴圈一搭配,長方形就出來了!
🔍 思考引導:
🧩 把大問題拆成小問題...
這題乍看很複雜,但可以分成幾個步驟:
- 第一步 — 搞懂圖案規律:觀察輸出,長方形每行的內容完全一樣,都是 C 個
*,共有 R 行。- 第二步 — 外層迴圈控制列數:需要跑 R 次,每次代表「印出一整行」。
- 第三步 — ???:你覺得在外層迴圈的每一次裡,內層需要做什麼?(提示:每行有 C 個
*)每個步驟單獨來看都不難,難的是把它們串起來!
輸入格式: 第一行:一個正整數 R(1 ≤ R ≤ 20) 第二行:一個正整數 C(1 ≤ C ≤ 20)
輸出格式: 共 R 行,每行恰好 C 個 *,不含多餘空格
範例一:
| 輸入 | 輸出 |
|---|---|
34 | ************ |
範例二:
| 輸入 | 輸出 |
|---|---|
25 | ********** |
範例說明:
- 第一步:讀入 R=3、C=4。
- 第二步:外層迴圈跑第 1 次(第 1 行)→ 內層印 4 個
*→ 輸出****,換行。 - 第三步:外層迴圈跑第 2 次(第 2 行)→ 內層同樣印 4 個
*→ 輸出****,換行。 - 第四步:外層迴圈跑第 3 次(第 3 行)→ 內層同樣印 4 個
*→ 輸出****,換行。 - 結論:外層共跑 3 次,每次內層印 4 個星號,產生 3×4 的長方形。
老師的提示
外層控制行數(跑 R 次),內層控制每行星號數(跑 C 次)。注意兩個 range 的上限是固定值(R 和 C),不會隨著目前跑到第幾行而改變——這正是長方形和三角形的關鍵差異。
星號倒三角形
問題情境:阿峰參加學校的程式設計社,社長每週都會出一道圖案挑戰讓社員練功。這週的題目是:「能不能讓星號從多到少,印出一個倒三角形?」阿峰覺得這題很有趣,因為之前學的直角三角形是從少排到多,現在要反過來。他接受挑戰,輸入 N 之後,第一行要印最多星號、最後一行只剩一個。阿峰在筆記本上把前幾行的星號數量列出來觀察,他發現關鍵在於:每一行的星號數量跟「目前是第幾行」有直接關係,只要把遞減的公式找出來,巢狀迴圈就能搞定!
🔍 思考引導:
🧩 把大問題拆成小問題...
這題乍看很複雜,但可以分成幾個步驟:
- 第一步 — 外層迴圈控制列數:從第 1 行跑到第 N 行,外層迴圈跑 N 次。
- 第二步 — 找出每行星號數的規律:第 i 行要印的星號數是 N-i+1(第 1 行 N 個,第 2 行 N-1 個,依此類推)。
- 第三步 — ???:你覺得內層迴圈要怎麼用「N-i+1」這個數字來印出正確數量的星號?
每個步驟單獨來看都不難,難的是把它們串起來!
🔀 試著補完這張流程圖...
下面的流程圖有些步驟被
???遮住了:
輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 20)
輸出格式: 共 N 行,第 i 行有 N-i+1 個 *
範例一:
| 輸入 | 輸出 |
|---|---|
4 | ********** |
範例二:
| 輸入 | 輸出 |
|---|---|
2 | *** |
範例說明:
- 第一步:讀入 N=4。
- 第二步:i=1,本行應印 4-1+1=4 個星號 → 輸出
****,換行。 - 第三步:i=2,本行應印 4-2+1=3 個星號 → 輸出
***,換行。 - 第四步:i=3,本行應印 4-3+1=2 個星號 → 輸出
**,換行。 - 第五步:i=4,本行應印 4-4+1=1 個星號 → 輸出
*,換行。 - 結論:外層跑 4 次,每次用公式 N-i+1 決定內層要印幾個星號,形成倒三角形。
老師的提示
這題與「等差遞減」直接相關:第 i 行印 N-i+1 個星號。當你設計內層迴圈時,思考 range(N - i + 1) 可以跑幾次——那就是這行要印幾個星號。
等腰三角形
問題情境:小涵在數學課學到等腰三角形,老師說等腰三角形最大的特色就是左右對稱。她忽然想到,如果能用程式把這個幾何概念視覺化,一定很酷。於是她給自己出了一道題:輸入高度 N,就能印出一個以 * 組成的等腰三角形。小涵在草稿紙上先手畫了幾行,發現每行的 * 數量和前面的空格數量都有規律,而且空格數加上星號數的總和似乎有固定的關係。她決定把「第幾行」跟「空格數」和「星號數」的公式找出來,用兩個內層迴圈分工合作,一個負責印空格、一個負責印星號,三角形就完成了!
🔍 思考引導:
🧩 把大問題拆成小問題...
這題乍看很複雜,但可以分成幾個步驟:
- 第一步 — 外層迴圈控制列數:從第 1 行跑到第 N 行,外層迴圈跑 N 次,每次代表一行。
- 第二步 — 計算每行需要的空格數:第 i 行前面有 N-i 個空格(第 1 行最多,最後一行 0 個)。
- 第三步 — ???:你覺得第 i 行應該印幾個
*?(提示:對照空格公式,試試2*i-1)每個步驟單獨來看都不難,難的是把它們串起來!
輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 20)
輸出格式: 共 N 行,第 i 行先印 N-i 個空格,再印 2i-1 個 *
範例一(N = 4):
| 輸入 | 輸出 |
|---|---|
4 | * *** ************ |
範例說明:
- 第一步:讀入 N=4。
- 第二步:i=1,空格數 = 4-1 = 3,星號數 = 2×1-1 = 1 → 輸出
*(3 空格 + 1 星號)。 - 第三步:i=2,空格數 = 4-2 = 2,星號數 = 2×2-1 = 3 → 輸出
***(2 空格 + 3 星號)。 - 第四步:i=3,空格數 = 4-3 = 1,星號數 = 2×3-1 = 5 → 輸出
*****(1 空格 + 5 星號)。 - 第五步:i=4,空格數 = 4-4 = 0,星號數 = 2×4-1 = 7 → 輸出
*******(0 空格 + 7 星號)。 - 結論:每行先印 N-i 個空格,再印 2i-1 個星號,兩個數字加起來固定為 N + i - 1,形成等腰對稱。
範例二(N = 3):
| 輸入 | 輸出 |
|---|---|
3 | * ******** |
老師的提示
每行有兩個任務:印空格和印星號。常見有兩種寫法:(1) 用兩個內層迴圈分別跑,一個負責印 n-i 個空格、一個負責印 2*i-1 個星號;(2) 用 1-2 學過的字串運算 print(" " * (n-i) + "*" * (2*i-1)) 一行印完,把空格字串跟星號字串串接起來。兩種方法都對,重點是把「行號 i」跟空格數、星號數的公式連結清楚。
數字金字塔
問題情境:阿偉在數學課迷上了數字的排列規律,有一天他在課本上看到巴斯卡三角形,覺得數字排成三角形的樣子非常漂亮。他決定先從簡單的開始練習:如果把「1、1 2、1 2 3、1 2 3 4」這樣的序列一行一行堆疊起來,就會形成一個數字金字塔!他想挑戰自己用程式重現這個圖案:輸入高度 N,程式就自動輸出 N 層的數字金字塔。阿偉拿出筆記本仔細觀察,注意到每行的數字個數等於行號,而且每行都從 1 開始遞增——這個規律就是解題的關鍵!
🔍 思考引導:
🧩 把大問題拆成小問題...
這題乍看很複雜,但可以分成幾個步驟:
- 第一步 — 外層迴圈控制列數:從第 1 行跑到第 N 行,每次外層迭代代表「印出一整行」。
- 第二步 — 內層迴圈印出數字序列:第 i 行要印出 1 到 i 共 i 個數字,數字之間用空格分隔。
- 第三步 — ???:你覺得怎麼確保最後一個數字後面不會多出一個空格?(提示:思考什麼時候印空格、什麼時候不印)
每個步驟單獨來看都不難,難的是把它們串起來!
🔀 試著補完這張流程圖...
下面的流程圖有些步驟被
???遮住了:
輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 15)
輸出格式: 共 N 行,第 i 行為 1 2 3 ... i
範例一(N = 4):
| 輸入 | 輸出 |
|---|---|
4 | 11 21 2 31 2 3 4 |
範例說明:
- 第一步:讀入 N=4。
- 第二步:i=1,內層 j 從 1 到 1,只印
1(唯一數字,不加後置空格)→ 輸出1,換行。 - 第三步:i=2,內層 j=1 印
1(後置空格),j=2 印2(不加後置空格)→ 輸出1 2,換行。 - 第四步:i=3,內層依序印
1、2、3→ 輸出1 2 3,換行。 - 第五步:i=4,內層依序印
1、2、3、4→ 輸出1 2 3 4,換行。 - 結論:外層 i 決定這行有幾個數字,內層 j 從 1 印到 i,關鍵是最後一個數字 j==i 時不加空格。
範例二(N = 2):
| 輸入 | 輸出 |
|---|---|
2 | 11 2 |
老師的提示
外層的行號 i 同時決定了內層要印幾個數字(印到 i 為止)。處理尾巴空格的常用技巧:用 if j < i 判斷「這不是最後一個數字」時才在後面加空格,最後一個數字(j == i 時)就不補空格,這樣行尾就不會留下多餘空白。
菱形圖案
問題情境:小嵐喜歡用程式創作幾何藝術,她之前已經成功印出了直角三角形和等腰三角形,現在她的新挑戰是印出一個菱形!她觀察到菱形的上半部就是一個等腰三角形,下半部是一個倒等腰三角形,兩者共用最寬的中間那行。小嵐想到一個策略:「與其把菱形當成一個整體來硬想,不如把它拆成上下兩半,分別用不同的迴圈處理。」這樣每一半都是她之前學過的三角形圖案,只要搞清楚上半部遞增、下半部遞減的方向,把兩段迴圈接在一起,菱形就完成了!
🔍 思考引導:
🧩 把大問題拆成小問題...
這題乍看很複雜,但可以分成幾個步驟:
- 第一步 — 上半部等腰三角形:從第 1 行到第 N 行,每行 i 印 N-i 個空格 + 2i-1 個
*(遞增)。- 第二步 — 下半部倒等腰三角形:從第 N-1 行倒回第 1 行,每行 i 印 N-i 個空格 + 2i-1 個
*(遞減)。- 第三步 — ???:你覺得上半部和下半部用同一個迴圈還是兩個迴圈比較清楚?兩個迴圈各自的
range要怎麼設?每個步驟單獨來看都不難,難的是把它們串起來!
🔀 試著補完這張流程圖...
下面的流程圖有些步驟被
???遮住了:
輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 10,代表菱形的半高,菱形共有 2N-1 行)
輸出格式: 共 2N-1 行,中間行最寬,上下各 N-1 行遞增/遞減
範例一(N = 3,共 5 行):
| 輸入 | 輸出 |
|---|---|
3 | * ******** *** * |
範例說明:
- 第一步:讀入 N=3,菱形共 2×3-1=5 行。
- 第二步(上半部,i=1 到 3):
- i=1:2 個空格 + 1 個星號 →
* - i=2:1 個空格 + 3 個星號 →
*** - i=3:0 個空格 + 5 個星號 →
*****(最寬中心行)
- i=1:2 個空格 + 1 個星號 →
- 第三步(下半部,i=2 到 1,從中心往下遞減):
- i=2:1 個空格 + 3 個星號 →
*** - i=1:2 個空格 + 1 個星號 →
*
- i=2:1 個空格 + 3 個星號 →
- 結論:上半部用 i 從 1 到 N 遞增,下半部用 i 從 N-1 到 1 遞減,公式相同但方向相反。
範例二(N = 2):
| 輸入 | 輸出 |
|---|---|
2 | **** * |
老師的提示
把菱形拆成上下兩個三角形來處理:上半部 for i in range(1, n+1) 印遞增的等腰三角形,下半部 for i in range(n-1, 0, -1) 印遞減的倒三角形。兩個迴圈用同一個公式(N-i 個空格 + 2i-1 個星號),只是遍歷順序相反。
配對計數
問題情境:阿彥在數學課學到「組合計數」,老師出了一道有趣的應用題:「1 到 N 之間,有多少組數字對 (i, j) 的和恰好等於 S?」阿彥覺得用手算太慢又容易出錯,決定寫一個程式來自動計算出答案。他在構思解法時注意到一個細節:為了避免重複計算(像 (3,7) 和 (7,3) 其實是同一對),需要規定 i ≤ j,這樣每一組配對就只會被算到一次。阿彥也發現這道題剛好可以用巢狀迴圈搭配條件判斷來解決,讓他體會到有時候數學公式可以幫你預測答案,而程式則能幫你逐一驗證!
🔍 思考引導:
💭 如果用數學來表達...
其中 i 是較小的數,j 是較大(或相等)的數。當 i 固定時,j 的值唯一確定為
。你覺得 j 需要滿足哪些條件才算是一個合法的數字對?(提示:j 必須滿足 且 )
🧩 把大問題拆成小問題...
這題乍看很複雜,但可以分成幾個步驟:
- 第一步 — 設計計數器:建立一個變數
count = 0來累計符合條件的數字對。- 第二步 — 外層迴圈遍歷 i:i 從 1 跑到 N,代表數字對中較小的那個數。
- 第三步 — 內層迴圈遍歷 j 並判斷:j 從 i 開始(確保 i ≤ j)跑到 N,若 i + j == S,則
count += 1。- 第四步 — ???:迴圈結束後,你覺得要輸出什麼?
每個步驟單獨來看都不難,難的是把它們串起來!
輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 100) 第二行:一個正整數 S(2 ≤ S ≤ 200)
輸出格式: 一個整數,代表符合條件的數字對個數
範例一:
| 輸入 | 輸出 |
|---|---|
1010 | 5 |
範例說明:
- 第一步:讀入 N=10,S=10,初始化 count=0。
- 第二步:遍歷 i=1 到 10,對每個 i 再遍歷 j=i 到 10,檢查 i+j 是否等於 10。
- 第三步:找到的合法數字對為 (1,9)、(2,8)、(3,7)、(4,6)、(5,5),共 5 對。
- 第四步:注意 i=6 時 j 需從 6 開始,6+6=12≠10;i=6, j=4 不合法(j<i),所以不計。
- 結論:符合 i+j=10 且 1≤i≤j≤10 的數字對有 5 組,輸出
5。
範例二:
| 輸入 | 輸出 |
|---|---|
57 | 2 |
老師的提示
關鍵在內層迴圈的起點:for j in range(i, n+1) 確保 j ≥ i,避免重複計算同一對數字。如果把條件改成 j = S - i,可以省掉內層迴圈,直接判斷 j 是否在合法範圍內——這是進階思路,但兩種方法都能拿到正確答案。
到這裡,2-4 的內容就全部結束了。你已經解鎖了巢狀迴圈這個強力工具!
本節小結
🎯 重點回顧:
- 巢狀迴圈:一個迴圈放在另一個迴圈裡,外層每跑一次,內層就完整跑一遍
- 外層控制行,內層控制列(或外層管理者、內層執行者)
- 總迭代次數 = 外層次數 × 內層次數
end=""+print()組合:用end=""讓同一行內輸出不換行,最後再呼叫print()換行- 縮排決定歸屬:
print()放在外層縮排才能每行換行一次 - 避免外內層變數同名:習慣上外層用
i,內層用j
📝 下一節:「模組二總結」:
你已經學完了模組二的全部內容:for 迴圈、while 迴圈、break/continue、巢狀迴圈。下一節是模組二的大複習,會整理一張知識地圖,幫你確認哪裡學紮實了、哪裡還需要加強,然後預告模組三的新挑戰。