PS용 파이썬 팁 모음
시작
파이썬으로 PS할 때에 유용한 팁들을 정리해봤다.
lru_cache
함수의 반환값을 기억해주는
lru_cache
def fibo(n):
if n < 2:
return n
return fibo(n - 1) + fibo(n - 2)
print(fibo(int(input())))
이런 DP문제는 위처럼 단순 재귀로 풀면 당연히 TLE가 뜬다.
그래서 메모이제이션(memoization)을 하면서 반복적인 계산을 줄여줘야 한다.
그런데 이 부분을 정말 쉽게 해결해주는 게 바로 functools
모듈의 lru_cache
함수다.
from functools import lru_cache
@lru_cache(maxsize=None)
def fibo(n):
if n < 2:
return n
return fibo(n - 1) + fibo(n - 2)
print(fibo(int(input())))
lru_cache
는 데코레이터로 사용되는데, 원하는 함수에 이 데코레이터를 달아 주면 반환값을 알아서 저장해준다.
전자가 lru_cache
를 사용한 코드, 후자가 데코레이터가 없는 코드다.
readline
반복해서 입력받아야 한다면
sys
모듈의stdin.readline
을 사용하자.
import sys
n = sys.stdin.readline()
단순히 한두번 입력받고 마는 문제라면 괜찮지만, 입력을 많이 받을 경우에 기본 input
함수를 사용하면 상당히 느려진다.
예시로 1725번: 히스토그램과 같이 여러번 입력받아야 하는 문제의 경우, readline
을 사용하면 시간이 엄청나게 단축되는 것을 볼 수 있다.
전자가 readline
사용, 후자가 기본 input
을 사용했을 때의 시간이다.
from sys import stdin
input = stdin.readline
나는 항상 readline
을 사용하려고 편하게 코드 맨 위에 이 코드를 적어놓는다.
🚨 주의사항
int(stdin.readline())
으로 사용할 때는 괜찮지만, 문자열을 입력받을 경우 맨 뒤의 개행 문자 (\n
)까지 그대로 입력받게 된다.
그러니 반드시stdin.readline().strip()
과 같이 사용하여 개행 문자를 제거해주자.
Asterisk, sep in print
리스트의 요소들을 출력해야 할 때, Asterisk(*)와
sep
인자를 잘 활용하면 간단하게 원하는 방식으로 출력할 수 있다.
l = [1, 2, 3, 4, 5]
for i in l:
print(i, end=" ")
# 1 2 3 4 5
for i in l:
print(i)
# 1
# 2
# 3
# 4
# 5
이번에 설명할 방법을 모른다면 위와 같은 방식으로 출력할 것이다.
하지만 *
연산자를 사용하면, 첫 번째 출력은 다음과 같이 줄일 수 있다.
print(*l)
아무런 기타 구문 없이 한 줄만으로 출력되는것을 볼 수 있다.
그리고 두 번째 출력은 *
연산자와 sep
인자를 사용해서 다음과 같이 줄일 수 있다.
print(*l, sep="\n")
*
인자를 단독으로 사용하면 요소들 사이에 공백이 들어가는데, sep
인자를 사용하면 요소들 사이에 들어갈 문자를 바꿔줄 수 있다.
위 예제에서는 요소들 사이에 들어갈 문자를 개행문자로 바꿔 한 줄에 하나씩 출력하게 된다.
map
map
은 이터레이터(iterator)이다.
입력을 받을 때 map
함수를 사용하는 경우가 많을 것이다.
m = map(int, input().split())
만약 1 2 3 4 5
와 같은 입력값을 map
을 이용해 위와 같이 입력받았는데, for
문으로 하나씩 사용해야 한다면 어떻게 하겠는가?
l = list(m)
for i in l:
print(i)
# 1
# ...
생각보다 위처럼 list
로 바꿔주는 사람들이 많았다. 그런데 사실 map
객체도 반복 가능한 객체(iterator)이다.
for i in m:
print(i)
# 1
# ...
그래서 그냥 위처럼만 해 줘도 잘 돌아가는 것을 볼 수 있다.
print(*m)
# 1 2 3 4 5
마찬가지로, 위에서 설명한 print
의 *
연산자를 활용한 예제에도 사용할 수 있다.
join
문자열 결합은
join
함수를 사용하자.
join
함수는 문자열들로 구성된 iterator
의 요소들을 결합해주는 함수이다.
l = ["a", "b", "c"]
", ".join(l)
# a, b, c
"".join(l)
# abc
정말 편리하게 요소들 사이에만 원하는 문자열을 추가해줘서, 맨 처음이나 마지막에 따로 처리를 할 필요가 없어진다.
set
중복 제거가 필요할 때는
set
set
객체는 대부분 알지만 많이 사용해보진 않았을 것이다.
>>> l = [1, 2, 5, 3, 4, 1]
>>> set(l)
{1, 2, 3, 4, 5}
set
에서는 중복을 제거해줄 뿐만 아니라 무려 정렬도 해 준다.
setrecursionlimit
파이썬에서 재귀함수를 사용한다면
setrecursionlimit
는 반 필수
이름 그대로 재귀 깊이를 설정해주는 함수다.
파이썬에서는 기본 재귀 깊이가 1000
밖에 되지 않기에 이 함수를 사용해서 깊이를 설정하고 문제를 푸는 게 좋다.
from sys import setrecursionlimit
setrecursionlimit(10 ** 4)
보통은 위와 같이 사용한다.
collections
적어도
Counter
는 사용하는 법을 알아 두자.
파이썬의 내장 모듈 중 collections
는 정말 유용한 모듈이다.
이 모듈에서 대표적인 객체는 deque
, Counter
등이 있는데,
deque
은 해당 자료구조가 필요한 문제라고 암시하는 경우가 많지만 Counter
는 정말 있으면 편한 순간이 많을 것이다.
from collections import Counter
c = Counter([1, 2, 3, 4, 5, 5, 5, 4, 2])
print(c)
# Counter({5: 3, 2: 2, 4: 2, 1: 1, 3: 1})
Counter
는 iterator
의 요소 개수를 세어 주는 객체라고 생각하면 된다.
게다가 c.most_common()
, for element, index in list(c.items())
등과 같은 정말 많은 함수, 사용 방법들이 있다.
여기서 설명하기에는 너무 많으니 직접 찾아보는걸 추천.
시간복잡도 관련
in
객체 안에 요소가 있는지 확인하는 in
연산자는 list
에서 사용할 경우 의 시간복잡도를 가지지만, set
에서 사용할 경우 무려 의 시간복잡도를 갖는다.
math.gcd의 TMI
파이썬의 내장모듈 math
에 들어있는 최대공약수를 구하는 함수 gcd
는 유클리드 알고리즘을 사용하며, 의 시간복잡도를 가진다.
끝
파이썬은 신이야
Author And Source
이 문제에 관하여(PS용 파이썬 팁 모음), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ombe1229/PS용-파이썬-팁-모음저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)