Python Counter와 Counter 사용 문제(백준 2108, 최빈값 찾기)
문제 2108 최빈값 찾기

2108번: 통계학
첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.
www.acmicpc.net
해당 문제 중 최빈값(mode)를 구하는 문제는 python에서는 collection의 Counter를 사용하는 것이 편하다고 한다.
(sort이후에 lst[i]==lst[i+1]로 풀라고하다가 계속 틀려서 counter를 이용했다..ㅎ)
대다수의 python으로 푼 최빈값 구하기 알로리즘에서 counter를 이용했기 때문에 간단히 이에 대해 정리하였다.
풀이는 바로 아래에 적어놓았다
풀이
mport sys
from collections import Counter
n = int(sys.stdin.readline())
lst = []
for i in range(n):
lst.append(int(sys.stdin.readline()))
lst.sort()
def get_mode(num):
if(len(num)==1):
return num[0]
cnt = Counter(num).most_common()
#most_conter 내림차순으로 가져옴
if cnt[0][1] != cnt[1][1]:
return cnt[0][0]
else:
array = []
for t in cnt:
if t[1] == cnt[0][1]:
array.append(t[0])
return sorted(array)[1]
avg = round((sum(lst)/n))
mid = lst[n//2]
mode = get_mode(lst)
diff = lst[-1] - lst[0]
print(avg)
print(mid)
print(mode)
print(diff)
Counter란?
https://docs.python.org/3/library/collections.html#collections.Counter
collections — Container datatypes
Source code: Lib/collections/__init__.py This module implements specialized container datatypes providing alternatives to Python’s general purpose built-in containers, dict, list, set, and tuple.,,...
docs.python.org
데이터의 개수를 셀 때 유용한 collections 모듈의 Counter 클래스가 python에는 존재한다.
Counter 생성자는 여러형태의 데이터를 인자로 받아 각 원소가 몇번씩 나오는지 저장된 객체를 반환한다.
from collections import Counter
Counter(['a','b','c','d','a','a','e','b','e','e','e'])
Counter({'e': 4, 'a': 3, 'b': 2, 'c': 1, 'd': 1})
이때 개수가 많은 것 부터 내림차순으로 반환한다
특정 원소의 개수를 얻으려면 다음과 같이 작성하면 된다.
from collections import Counter
cnt = Counter(['a','b','c','d','a','a','e','b','e','e','e'])
#Counter({'e': 4, 'a': 3, 'b': 2, 'c': 1, 'd': 1})
cnt[0][0] #e
cnt[0][1] #4
cnt[a] #3
.most_common()
개수가 많은 순서(최빈인 순서)부터 k개를 리턴하는 함수로, 매개변수로 값을 넘기지 않으면, 동일하게 내림차순으로 값을 반환한다.
cnt = Counter(['a','b','c','d','a','a','e','b','e','e','e'])
cnt.most_common()
[('e', 4), ('a', 3), ('b', 2), ('c', 1), ('d', 1)]
cnt.most_common(2)
[('e', 4), ('a', 3)]
추가적인 연산과 함수들
+, - 산술 연산
cnt1= Counter(['a','b','c','d','a','a','e','b','e','e','e'])
cnt2 = Counter(['a','b','d','d'])
cnt1+cnt2
Counter({'a': 4, 'e': 4, 'b': 3, 'd': 3, 'c': 1})
cnt1-cnt2
Counter({'e': 4, 'a': 2, 'b': 1, 'c': 1})
#음수나 0이 되면 사라짐
subtract(): 음수를 포함해주는 - 연산
cnt1= Counter(['a','b','c','d','a','a','e','b','e','e','e'])
cnt2 = Counter(['a','b','d','d'])
cnt1.subtract(cnt2)
cnt1
Counter({'e': 4, 'a': 2, 'b': 1, 'c': 1, 'd': -1})
&(교집합), 합집합(|)
cnt1= Counter(['a','b','c','d','a','a','e','b','e','e','e'])
cnt2 = Counter(['a','b','d','d'])
cnt1&cnt2
Counter({'a': 1, 'b': 1, 'd': 1})
cnt1|cnt2
Counter({'e': 4, 'a': 3, 'b': 2, 'd': 2, 'c': 1})
elements() :ist로 재변환(카운터 숫자만큼)
cnt1= Counter(['a','b','c','d','a','a','e','b','e','e','e'])
cnt1
Counter({'e': 4, 'a': 3, 'b': 2, 'c': 1, 'd': 1})
cnt1.elements()
<itertools.chain object at 0x000001BD78F54820>
list(cnt1.elements())
['a', 'a', 'a', 'b', 'b', 'c', 'd', 'e', 'e', 'e', 'e']
list(cnt1)
['a', 'b', 'c', 'd', 'e']