Study/Baekjoon Online Judge

[백준/파이썬] 2108. 통계학

growingtree 2022. 2. 25. 14:02

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

 

문제 

수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.

  1. 산술평균 : N개의 수들의 합을 N으로 나눈 값
  2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
  3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값
  4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이

N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.

 

입력

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

 

출력

 

첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.

둘째 줄에는 중앙값을 출력한다.

셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.

넷째 줄에는 범위를 출력한다.

 

아이디어

- 산술평균 : sum(숫자 리스트) / len(숫자 리스트)  , 반올림 round() 

- 중앙값 : 정렬 , len(숫자 리스트)//2 를 활용

- 최빈값 : counter 사용, 최빈값이 여러개인 경우, 1개인 경우 나눠서 생각

- 범위 : 최소값과 최대값이 양수인지 음수인지 확인 후 양수일때, 음수일때 나눠서 분기문 처리 

 

코드 

# 2108. 통계학

from collections import Counter
import sys 

# 일단 전체 필요한 수 입력받기
numbers = [int(sys.stdin.readline()) for _ in range(int(sys.stdin.readline()))]


# 1. 산술평균
print(round(sum(numbers) / len(numbers)))

# 2. 중앙값
print(sorted(numbers)[len(numbers)//2]) #복잡도 : NlogN

# 3. 최빈값
cnt = Counter(numbers).most_common()

big = cnt[0][1]
lis = []

for x in cnt:  
    if x[1] == big:
        lis.append(x)
    
if len(lis) != 1:
    lis = sorted(lis)
    print(lis[1][0])
else: 
    print(lis[0][0])

# 4. 범위
min_value = min(numbers)
max_value = max(numbers)

if max_value > 0 and min_value > 0 :
    print(max_value-min_value)
elif max_value > 0 and min_value < 0 :
    print(max_value - min_value)
else:
    print(abs(abs(max_value) - abs(min_value)))

 

해설

# 2108. 통계학
from collections import Counter
import sys 

# 입력값으로 들어온 숫자들을 numbers 라는 리스트로 저장
numbers = [int(sys.stdin.readline()) for _ in range(int(sys.stdin.readline()))]


# 1. 산술평균
# 리스트에 들어있는 수 전부를 더하고 (sum) , 리스트의 길이(len) 로 나눈다.  
# 첫째자리에서 반올림하니까 round 함수에는 인수를 넣지 않는다.
print(round(sum(numbers) / len(numbers)))

# 2. 중앙값
# 중앙값을 구하기 위해 오름차순으로 정렬(sorted)
# 정렬된 리스트에 가운데 값 : 리스트 길이를 2로 나눈 몫(//) 을 인덱스값으로 준다.
print(sorted(numbers)[len(numbers)//2])

# 3. 최빈값 : 최빈값을 구하기 위해 Counter 사용
# Counter의 most_common() 메소드는 numbers리스트에 존재하는 모든 숫자들의 개수를 센 후 
# 개수가 많은 수(count가 많이 된 수)부터 정렬되어  딕셔너리 형태로 리턴 {숫자:등장횟수}
cnt = Counter(numbers).most_common()

# big 변수에는 가장 많이 등장한 수의 count 값이 들어있음(최빈값)
big = cnt[0][1]

# 최빈값을 담을 빈 리스트 lis 선언
lis = []

# 리스트를 돌면서 최빈값이 여러개인 경우가 있는지 체크 있으면 lis 에 저장
for x in cnt: 
   if x[1] == big:
        lis.append(x)

# 만약 lis의 길이가 1이 아니면 (즉, 최빈값의 개수가 여러개면
# → lis를 다시 오름차순으로 정렬 후 최빈값중 두 번째로 작은 값(리스트 상 1번째 값) 을 출력한다. 
if len(lis) != 1:
    lis = sorted(lis)
    print(lis[1][0])
    
# 만약 리스트의 길이가 1이면 그냥 lis의 0번째 값을 출력하면 된다. 
else: 
    print(lis[0][0])


# 4. 범위

# 리스트 내 최솟값과 최댓값을 각각 min_value 와 max_value로 저장
min_value = min(numbers)
max_value = max(numbers)

# 만약 최댓값이 양수면서 최솟값도 양수인 경우 그냥 둘을 빼면 범위가 구해진다.
if max_value > 0 and min_value > 0 :
    print(max_value-min_value)

# 최댓값이 양수인데 최솟값은 음수인 경우 둘을 빼서 범위를 구한다.
elif max_value > 0 and min_value < 0 :
    print(max_value - min_value)

# 위 두 경우가 아니면, 최댓값이 음수면서 최솟값은 음수인 경우하나밖에 없음 
# 이러한 경우 최댓값,최솟값 모두 절대값을 취하고, 그 결과또한 절대값을 취해서 출력한다 (음수의 경우 절대값이 큰게 최솟값이기 때문)
else:
    print(abs(abs(max_value) - abs(min_value)))
반응형