문제풀이/BOJ

[Python] BOJ/백준 2108번 통계학

서채리 2021. 8. 7. 23:58

[문제]

https://www.acmicpc.net/problem/2108

 

2108번: 통계학

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

www.acmicpc.net

 


[풀이]

산술평균, 중앙값, 범위 구하는 법은 쉬워서 패스.. 최빈값 구하는 게 아주 조금 까다로웠다.

 

처음에 입력 받을 때 sorted함수를 통해 차례대로 정렬한 상태로 리스트에 저장한다.

 

num_cnt 딕셔너리를 생성한 후 try-except문을 활용해 num_cnt에 숫자 당 빈도수를 저장했다.

for문으로 num에 있는 숫자를 차례대로 꺼내 num_cnt[i] += 1을 하게 되면

num_cnt[i]가 있을 경우에는 원래 있던 값에 1이 더해지고,

num_cnt[i]가 없었을 경우에는 except문을 통해 num_cnt[i]를 1로 초기화한다.

 

그 후 빈도수 값(딕셔너리의 value)만 모아 리스트를 만든 후 max() 함수를 통해 구한 가장 큰 수를 mode_num 변수에 담는다.

 

mode값을 담을 리스트를 생성한 후 num_cnt 딕셔너리를 차례대로 돌아 value값이 위에서 구한 mode_num과 일치할 경우 해당 key 값을 mode 리스트에 추가한다.

 

값을 차례대로 출력해주는데 만약 mode값이 1개일 경우에는 mode[0]을 출력하고, 2개 이상일 경우에는 두 번째로 작은 mode값인 mode[1]을 출력한다. 

 

++ 근데 티스토리 기본모드는 인라인코드가 안되네 가독성 너무 떨어진다..

 


[코드]

import sys

if __name__ == '__main__':
    num = sorted([int(sys.stdin.readline()) for _ in range(int(sys.stdin.readline()))])

    average = round(sum(num) / len(num))    # 산술평균
    median = num[(len(num) // 2)]   # 중앙값

    num_cnt = {}    # key: 입력받은 숫자, value: 숫자 당 빈도수
    for i in num:
        try:
            num_cnt[i] += 1
        except:
            num_cnt[i] = 1
    mode_num = max(list(num_cnt.values()))  # 딕셔너리의 value만 모아 리스트로 만든 후 그 중 최대값

    mode = []
    for i in num_cnt:
        if num_cnt.get(i) == mode_num:
            mode.append(i)

    # 출력
    print(average, median, sep='\n')
    if len(mode) < 2:
        print(mode[0])
    else:
        print(mode[1])
    print(abs(num[-1]-num[0]))