Python Counter, 빈도수를 쉽게 세는 방법
Python collections.Counter로 원소의 빈도수를 세고 알고리즘 문제에 활용하는 방법을 정리한다.
Counter
빈도수를 세는 문제에서 코드를 확 줄여주는 기능이다.
Counter는 collections 모듈에서 가져와 사용한다.
from collections import Counter
기본 형태는 다음과 같다.
Counter(이터러블)→{원소: 등장 횟수}형태로 세어준다.
from collections import Counter
nums = [1, 2, 2, 3, 3, 3]
count = Counter(nums)
print(count[2])
2
문자열도 문자 하나씩 순회할 수 있는 이터러블이므로 카운팅할 수 있다.
count = Counter("banana")
print(count)
# Counter({'a': 3, 'n': 2, 'b': 1})
알고리즘 문제에서 자주 쓰는 기능
count = Counter(nums)
count[x] # x의 개수, 없으면 0
count.most_common(1) # 가장 많이 나온 값 1개
count.keys() # 등장한 값들
count.values() # 각 값의 등장 횟수
count.items() # (값, 등장 횟수)
예를 들어 각 귤 크기의 개수를 센 뒤, 등장 횟수만 가져오고 싶다면 다음처럼 사용할 수 있다.
tangerine = [1, 3, 2, 5, 4, 5, 2, 3]
counts = list(Counter(tangerine).values())
print(counts)
# [1, 2, 2, 2, 1]
특히 이런 문제에서 유용하다
- 문자열의 문자 개수 세기
- 숫자별 등장 횟수 세기
- 애너그램 판별
- 최빈값 찾기
- 두 배열의 원소 구성 비교
- 중복 원소 찾기
애너그램은 문자의 순서는 다르지만, 사용된 문자와 각 문자의 개수가 같은 단어를 말한다.
Counter("listen") == Counter("silent") # True
개인적인 고민
모든 기능을 내가 구현해야 하는 게 아닌가?
나는 약간 내가 직접 구현해야 할 것 같은 강박이 있다.
하지만 이런 강박을 가질 필요는 없다.
알고리즘 문제에서는 단순히 코드를 길게 짜는 능력만 보는 것이 아니다.
- 이 문제가 빈도수를 활용해서 해결할 수 있는 문제인지 알아보는가?
- 어떤 자료구조를 사용해야 하는지 판단할 수 있는가?
- 시간 복잡도를 고려할 수 있는가?
빈도수를 딕셔너리에 저장하는 반복문은 이미 검증된 도구로 대체할 수 있는 구현 세부 사항이다.
굳이 검증된 도구가 있다면 매번 다시 만들어서 쓸 필요는 없다.
직접 구현한다면
count = {}
for x in nums:
count[x] = count.get(x, 0) + 1
Counter를 사용한다면
count = Counter(nums)
둘 다 핵심 원리는 똑같고, 평균 시간 복잡도도 보통 O(N)이다.
따라서 Counter를 사용했다고 해서 알고리즘을 건너뛴 것은 아니다.
추천 학습 방식
- 처음에는 빈도수 계산을 직접 구현해보며 원리를 이해한다.
- 이후 문제에서는
Counter를 사용한다. - 라이브러리 사용이 금지된 문제나 코딩 테스트 환경에서 지원하지 않는 경우에만 직접 구현한다.
Counter없이도 구현 방법을 설명할 수 있으면 충분하다.
다만 아래 알고리즘과 자료구조는 동작 원리를 이해하기 위해 직접 구현해보는 것이 좋다.
- 정렬, 이분 탐색
- 스택, 큐
- BFS, DFS
- 힙
- 유니온 파인드
- 다익스트라
결론
문제가 빈도수 문제라는 것을 알아보는 것도 알고리즘 실력이다.
원리는 직접 이해하고, 실전에서는 표준 라이브러리를 적극적으로 사용하자.
COMMENTS
GitHub 계정으로 로그인하여 댓글을 남길 수 있습니다. 댓글은 GitHub Discussions에 공개 저장되며, 작성 내용과 GitHub 프로필 정보가 다른 방문자에게 보일 수 있습니다.