🐍 Python 排列組合大師班:itertools 終極指南

在程式解題(如 CPE 檢定)或是日常開發中,我們經常遇到需要「窮舉所有可能性」的情況。手寫多層 for 迴圈不僅容易出錯,程式碼也會變得冗長難讀。

Python 內建的 itertools 模組提供了兩把終極神兵:**permutations (排列)** 與 **combinations (組合)**。它們底層由 C 語言實作,執行速度極快,是演算法考場上必備的去超時 (TLE) 武器。


💡 核心判斷準則:我該用哪一個?

全天下只有一個黃金判斷標準:「順序不一樣,算是同一種結果嗎?」

  • 順序 有差 ➡️ 用 permutations (排列)
  • 順序 沒差 ➡️ 用 combinations (組合)

⚔️ 兵器一:Permutations (排列)

「順序超級重要!誰站前面、誰站後面,結果完全不一樣。」

  • 數學意義: 從 $n$ 個物品中挑出 $k$ 個進行排列,公式為 $$P(n, k) = \frac{n!}{(n-k)!}$$
  • 生活情境: 設定手機密碼(1221 是不同密碼)、賽跑名次(金牌與銀牌)。
  • 特色: 會窮舉所有位置變換的可能性,產生的結果數量較多。

💻 程式碼範例

1
2
3
4
5
6
7
8
9
10
from itertools import permutations

# 陣列裡有 3 個數字
items = [1, 2, 3]

# 任務:從中挑選 2 個數字進行「排列」
print("=== Permutations (排列) ===")
for p in permutations(items, 2):
print(p)

輸出結果 (共 6 種):

(1, 2)
(1, 3)
(2, 1) <– 注意!因為順序有差,所以 (2, 1) 也是一種獨立的結果。
(2, 3)
(3, 1)
(3, 2)


🛡️ 兵器二:Combinations (組合)

「有挑到就好,排隊順序隨便啦!」

  • 數學意義: 從 $n$ 個物品中挑出 $k$ 個組成集合,不考慮順序,公式為
    $$C(n, k) = \frac{n!}{k!(n-k)!}$$

  • 生活情境: 買樂透(先劃 10 號或先劃 20 號,中獎結果一樣)、打果汁(蘋果和香蕉一起放進果汁機)。

  • 特色: 遇到相同的元素群體只會保留一次,並且會「自動保持元素原本的相對順序」(例如由小到大)。

💻 程式碼範例

1
2
3
4
5
6
7
8
9
10
from itertools import combinations

# 陣列裡有 3 個數字
items = [1, 2, 3]

# 任務:從中挑選 2 個數字進行「組合」
print("=== Combinations (組合) ===")
for c in combinations(items, 2):
print(c)

輸出結果 (共 3 種):

(1, 2)
(1, 3)
(2, 3)
(註:絕對不會出現 (2, 1),因為它跟 (1, 2) 是同一組人馬!)


📊 考場極速對照表

英文兵器名中文核心問題:順序有差嗎?經典題型結果數量
permutations排列有差! (A, B) $\neq$ (B, A)字謎 (Anagram)、密碼破解很多
combinations組合沒差! (A, B) =$ (B, A)樂透 (Lotto)、湊數字 (Sum It Up)較少

🚀 CPE 實戰小技巧

  1. 偷懶縮寫法: 考場上如果不想打太長的單字,可以善用 import ... as

    1
    2
    3
    4
    from itertools import combinations as cb
    for combo in cb([1, 2, 3], 2):
    print(*combo) # 利用 * 號解壓縮,自動用空白隔開印出

  2. 只求總數不求過程: 如果題目只問「總共有幾種可能?」,千萬不要跑迴圈!直接召喚數學黑魔法:

    1
    2
    3
    4
    import math
    # 算出從 5 個挑 3 個的組合數量
    total = math.comb(5, 3)