알고리즘(algo)/백준
[백준] 2108번 - 통계학
dDong2
2023. 1. 27. 11:24
참고: https://www.acmicpc.net/problem/2108
✔️ 문제
문제는 다음과 같다.
✔️ 풀이
해당 문제의 입력과 출력 예시는 중요한 반례들만 들어있다.
1과 3에서는 최빈값이 여러개 일때, 두 번째로 작은 값을 출력하는 반례가 있고
2에서는 1개 입력을 받았을 때의 범위가 0이라는 것,
4에서는 평균 값이 올림이 아닌 반올림을 해주어야한다는 것이다.
1) 리스트를 받아서 정렬하고 round 및 sum을 활용한다.
2) 정렬한 리스트의 끝값과 첫값의 차이가 범위이다.
3) 정렬한 리스트를 반으로 나눈 인덱스가 중간 값이다.
이렇게는 금방 해결할 수 있었지만,
최빈값을 구하고 그 중에서도 여러 최빈값의 두 번째로 작은 값에
해당하는 조건이 가장 까다로웠다.
import sys
from collections import Counter
ss=sys.stdin.readline
N=int(ss())
data=sorted([int(ss()) for _ in range(N)])
a=round(sum(data)/N)
b=data[int(N/2)]
c=data[0] if N==1 else data[1] if data==sorted(list(set(data))) else max(data, key=data.count) if Counter(data).most_common(n=2)[0][1]!=Counter(data).most_common(n=2)[1][1] else Counter(data).most_common(n=2)[1][0]
d=max(data)-min(data)
print(a,b,c,d,sep='\n')
처음에는 max(data, key=data.count)라는 공식을 사용하여
리스트에서 가장 횟수가 많은 값을 즉, 최빈에 해당하는 값을
뽑아서 처리할 수 있었지만 시간 초과에 걸리게 되었다.
참고로 Counter는 중복 갯수를 세기 위한 방법으로
https://hengbokhan.tistory.com/184 해당 주소를 참고하여
로직을 작성하였는데, 시간 초과를 해결하기 위해서
다음과 같이 로직을 수정하였다.
import sys
from collections import Counter
ss=sys.stdin.readline
N=int(ss())
data=[int(ss()) for _ in range(N)]
print(round(sum(data)/N))
data.sort()
print(data[int(N/2)])
many=Counter(data).most_common()
if len(many) > 1:
if many[0][1] == many[1][1]:print(many[1][0])
else:print(many[0][0])
else:print(many[0][0])
print(data[-1]-data[0])
중복 갯수가 가장 많은 첫 번째와 두 번째를 비교해서
값이 같으면 두 번째를 출력하고 그렇지 않으면 첫 번째를 출력한다.
Counter의 most_common 함수를 알아가게 된 문제였다.
화이팅 💪