알고리즘(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 함수를 알아가게 된 문제였다.

 

화이팅 💪