【Python】競程相關模組、函數、方法等整理 - part 1
【Python】競程相關模組、函數、方法等整理 - part 1
因為最近又要比賽了,所以趕緊做一篇整理複習一下,然後備註一下:這是個人筆記。
IO優化
輸入優化
使用前引入模組:import sys
或 from sys import stdin,這樣方法就不用多打 sys。
1 | from sys import stdin |
若讀到 EOF 會回傳空字串。
建議搭配 strip() 函數使用:
1 | from sys import stdin |
stdin.readline():每次讀取一行資料,直到\n為止。由於回傳的字串通常包含\n,若不需要,用 strip() 去除。stdin.readlines():一次讀完 stdin,會回傳 list。stdin.read():讀取整個輸入流的所有資料,直到 EOF。適合一次性讀取大量資料。
以下使用迭代的方式處理 stdin 檔:
1 | from sys import stdin |
不用特地處理 EOF,迭代完即退出迴圈。
輸出優化
使用前引入模組:from sys import stdout
stdout.write():
- 將字串輸出至標準輸出流。
- 不會自動幫你加
\n,要加記得加。 - 除回傳字串外,也會回傳所寫的字元總數。
1 | from sys import stdout |
output:
1 | Hello, World! |
stdout.writelines():
- 參數必為 iterable 物件。
- 迭代這個物件的每一個元素並寫入 stdout 檔。
- 無回傳值(None)。
- 若傳入的參數是字串,則
stdout.writelines()的速度遠慢於stdout.write()。
相關應用
有個 list a,然後遍歷他所有的元素。
1 | from sys import stdout |
output:
1 | 1 2 3 4 5 6 7 8 9 10 |
使用 str.join() 方法,搭配 map() 函數可減少輸出時間。
如果使用 for 迭代方式:
1 | from sys import stdout |
會慢很多且無效率。
多個變數輸入處理
1 | from sys import stdin |
math 模組
須引入模組 import math。
引入特定方法:from math import <要用的方法>
math.gcd(*integers), Python 3.5
回傳指定整數引數的最大公因數。若存在任一非零引數(Arguments),回傳值為所有引數共有因數中最大的正整數。若所有引數皆為零,則回傳值為 0。gcd() 若未傳入任何引數也將回傳 0。
1 | from math import gcd |
output:
1 | 4 |
math.lcm(*integers), Python 3.9
回傳指定整數引數的最小公倍數。若所有引數值皆非零,回傳值為所有引數共有倍數中最小的正整數。若存在任一引數值為零,則回傳值為 0。lcm() 若未傳入任何引數將回傳 1。
1 | from math import lcm |
output:
1 | 60 |
若因為 Python 版本問題,可使用公式 GCD (a, b) = (a × b)/ LCM (a, b),直接求 lcm()。
math.factorial(n)
以整數回傳 n 的階乘。若 n 非整數型別或其值為負會引發 ValueError。
1 | from math import factorial |
output:
1 | 120 |
5! = 1 2 3 4 5 = 120
- math.ceil(x):向上取整
- math.floor(x):向下取整
floor(x) 實則為高斯函數 f(x) = [x] (參見高三上數甲)。
1 | from math import ceil |
output:
1 | 3 |
1 | from math import floor |
output:
1 | 2 |
eval()
註:這是神兵利器,但比賽有可能會 ban 這個函數。
eval() 函數可用來執行一個字串運算式,並回傳運算式的值。
1 | eval(expression[, globals[, locals]]) |
expression:運算式
globals:變數作用域,若提供,則為 dictionary 物件。
locals:變數作用域,若提供,可為任何被 mapping 的物件。
以下範例在 Python Shell 裡執行:
1 | x = 7 |
ord()
1 | ord(c) |
c:character 字元。
將字元轉成十進位 Unicode 字元。
1 | >>>ord('a') |
註:與其相反的就是 chr() 函數,用法相同,chr() 將 Unicode 字元輸出為字母。
sum()
1 | sum(iterable[, start]) |
iterable:可迭代物件,如:list、tuple、set 等。
start:指定相加的參數,如果沒有設定這個值,預設為 0。
功能:求和用。
1 | >>>sum([0,1,2]) |
進制轉換
bin():轉二進位函數
1 | bin(x) |
x:int 或 long int 數字
該函數會回傳字串。
1 | >>> |
要去掉 0b,可做以下動作:
1 | bin(10)[2:] |
[2:] 將字串做切片擷取,從 2 開始擷取至結束。(因為這是字串所以可以這樣做)
oct():轉八進位函數
1 | oct(x) |
x:整數。
回傳 8 進位字串。
1 | oct(10) |
要去掉 ‘0o’ 的話就跟上面作法一樣。
hex():轉十六進位函數
1 | hex(x) |
x:整數。
回傳 16 進位字串。
1 | >>>hex(255) |
排序方法
結論:用 sort() 比較快。
sorted()
1 | sorted(iterable, cmp=None, key=None, reverse=False) |
iterable:可迭代物件。
cmp:比較函數,具有兩參數,參數的值從可迭代物件中取出,此函數必須遵守的規則為:大於則傳回 1,小於則傳回 -1,等於則傳回 0。
key:主要用來比較的元素,只有一個參數,具體的函數的參數就是取自於可迭代物件中,指定可迭代物件中的一個元素來進行排序。
reverse:排序規則,reverse = True 降序,reverse = False 升序(預設)。
不過建議用 key,cmp 太慢。
回傳 list。
1 | a = [5,7,6,3,4,1,2] |
1 | a = [('b',1),('a',2),('c',4),('d',3)] |
sort()
1 | list.sort(cmp=None, key=None, reverse=False) |
參數說明同上。
此方法沒有回傳值,但會對列表的物件進行排序。
1 | a = [5,4,2,7,1,3,466,77,0] |
sorted() v.s sort()
兩者差在哪?
sort() 專門用在 list 資料型態。
sorted() 則是所有可迭代物件皆可用。
zip()
1 | zip([iterable, ...]) |
可將可迭代物件之對應的元素打包成一個元組。
回傳值:list 包著 tuple(元組列表)
1 | a = [1,2,3] |
Tip:看列表直行,就是要打包的元組,像是 a、b 的 a[0]、b[0] 會被一起打包 -> (1,4)。
enumerate()
1 | enumerate(sequence, [start=0]) |
sequence:序列。迭代器或可迭代物件。
start:index 從何處開始列舉。
回傳值為:enumerate(列舉)物件。
反正這東西可列舉序列中的元素位置(index),如下:
1 | seasons = ['Spring', 'Summer', 'Fall', 'Winter'] |
以下展示了使用 for 迴圈跟結合 enumerate() 函數的區別:
1 | # 一般用法 |
1 | # 使用 enumerate() |
生成式(Comprehension)
參見:https://hackmd.io/@LukeTseng/SJ36tHV1A
deque(雙端佇列)
使用前引入模組:from collections import deque。
初始化一個 deque 可:a = deque()
deque 物件有以下方法:
append(x):將 x 丟到 deque 的末端。appendleft(x):將 x 丟到 deque 的左端。clear():清除所有 deque 元素且長度為 0。copy():建立一個 deque 的淺複製。count(x):計算 deque 內元素為 x 的個數extend(iterable):將可迭代物件(如 list 等)擴展在 deque 末端。extendleft(iterable):將可迭代物件(如 list 等)擴展在 deque 左端。index(x[, start[, stop]]):回傳 deque 中 x 的位置(或在索引 start 之後、索引 stop 之前的位置)。回傳第一個匹配的位置,如果沒找到就引發 ValueError。insert(i, x):在 deque 位置 i 中插入 x。pop():移除並回傳 deque 的末尾元素。popleft():移除並回傳 deque 的最左端元素。remove(value):移除第一個出現的 value,如果沒找到的話就引發一個 ValueError。reverse():將 deque 中的元素原地 (in-place) 倒序排列並回傳 None。
那這可以幹嘛?用在 BFS、DFS。
bisect(二分搜)
使用前引入模組:import bisect
二分搜前置條件是要已排序的序列才可以二分搜。
函數如下:
bisect.bisect_left(a, x, lo=0, hi=len(a), key=None):回傳序列 a 中 x 出現的第一個位置(輸出 index 值)。bisect.bisect_right(a, x, lo=0, hi=len(a)):與上相反,回傳 x 出現的最後一個位置的索引再 + 1。bisect.bisect(a, x, lo=0, hi=len(a)):等同於bisect.bisect_right。
1 | import bisect |
二分搜時間複雜度:
排列組合好幫手:itertools
使用前引入模組:import itertools
- itertools.permutations(iterable, r=None):排列,回傳 iterable 中連續且長度為 r 的元素排列。r 若無設定則預設為序列長度。
這東西就是:
m = r + 1,假設 n = 5,r = 2 就會是以下數學式:
1 | import itertools |
以上的意思就等同:
然後會列出 12 種排列可能性。
1 | [('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'A'), ('B', 'C'), ('B', 'D'), ('C', 'A'), ('C', 'B'), ('C', 'D'), ('D', 'A'), ('D', 'B'), ('D', 'C')] |
- itertools.combinations(iterable, r):組合,從輸入 iterable 中回傳長度為 r 的元素的子序列。
公式:
1 | import itertools |
1 | [('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')] |
寫成數學式就是:
跟輸出一樣,具有六種可能性。
lambda應用:三大常用函數
map()
語法:
1 | map(function, iterable, ...) |
function:函數。
iterable:可迭代物件。
回傳一個迭代器物件。
map 就是映射的意思,把 function 映射到 iterable 上面去,如下:
1 | a = ['1', '2', '3', '4'] |
輸出:
1 | [1, 2, 3, 4] |
以上範例為將 int() 函數全部套用在 a 列表內的所有元素內。
filter()
1 | filter(function, iterable) |
function:函數。
iterable:可迭代物件。
回傳一個迭代器物件。
這東西就是用 function 去過濾 iterable 的一些元素,把它篩選掉,如下範例:
1 | list(filter(lambda x: x%2==0, [1,2,3,4,5,6,7,8,9,10])) |
把不是偶數的都篩掉了,這個意思就是把列表所有元素丟進去函數裡面運算,如果 x % 2 == 0 運算出來是 true 的話就留著,不是就把它丟掉。
然後這程式碼可以更簡化寫成:
1 | list(filter(lambda x: x%2==0, range(1,11))) |
range(1, 11) 自動生成 1 ~ 10 的 list。
reduce()
Python 3.x 已移到 functools,請引入:from functools import reduce
語法:
1 | reduce(function, iterable[, initializer]) |
function:帶有兩個參數。
該函數 reduce() 回傳函數計算結果。
reduce() 的運算原理:先將序列中兩個元素當作 function 的參數,運算完之後,function 的結果再跟下一個元素繼續丟 function 運算,算到不能再算為止。
1 | from functools import reduce |
以上這個輸出結果其實就是列表元素的和:
但要用這個去做求和,不如用:sum(range(1,6))。
然後如果我們用 reduce() 去解釋,就像:
先將 1, 2 拉出來當參數,然後 1 + 2 = 3 結果出來後,3, 3 再當參數,依此類推,因此最後可以得到 15。
參考資料
collections — Container datatypes — Python 3.13.2 documentation
Built-in Functions — Python 3.13.2 documentation
bisect — Array bisection algorithm — Python 3.13.2 documentation
itertools — Functions creating iterators for efficient looping — Python 3.13.2 documentation
math —- 數學函式 — Python 3.13.2 說明文件




