본문 바로가기
알고리즘 풀이

[algorithm] 페어 - 백준:2108 통계학

by 째깍단 2023. 5. 4.

답:

더보기
import sys
from collections import Counter

input = sys.stdin.readline

N = int(input())
num_list = []

for _ in range(N):
    num_list.append(int(input()))
num_list.sort()

#평균값
average = sum(num_list)/N
print(round(average)) 

#중앙값
median = num_list[int(N/2)]
print(median)

#최빈값
array = {}
array = Counter(num_list)  
most = array.most_common()
if len(array) == 1:
    print(most[0][0])    
elif most[0][1] == most[1][1]:
    print(most[1][0])
else:
    print(most[0][0])

#범위
num = num_list[-1] - num_list[0] 
print(num)

 

어유 길어.. 열심히 풀었다! 장하다!

 

 

 

 

 

문제 분석 및 해석

 

 

입력:

첫째 줄에 수의 개수 N

N개의 줄에는 정수 가 주어진다

 

출력:

산술평균, 중앙값, 최빈값, 범위가 차례로 출력

 

 

 

1) 풀이 생각

-1 첫번째 줄에서 입력하는 개수 따로 입력받고

 

-2 n개의 줄에 입력받기, input()은 한개만 있어도 되지만, 자리할 곳을 마련해주어야함!

list에 입력받도록 하자.

 

-3 list에 들어간 정수들을 각각의 계산식에 넣어준다. ==이렇게 단순하게 생각하지말고 구체적으로 풀이를 써보자!

산술평균

중앙값

최빈값

범위

 

 

 

 

 

- 과정1 - 평균, 중앙값

 

평균은 모두 더한 후 N 만큼으로 나누어주기!

 

average = sum(num_list)/N
print(round(average))

 

round 로 감싸주어 평균값을 반올림하고 정수로 출력하도록 했다.

** round로 감싸지 않으면 예제 출력 시 float가 나와 list out of range 오류가 뜬다

 

 

 

 

중앙값은 N을 2로 나누어 정수화 시킨 index값 넣어주기

 

median = num_list[int(N/2)]
print(median)

 

 

 

 

 

- 과정2 -  최빈값

 

 

최빈값을 구하기 위해 Counter 를 사용, most_common()으로 값을 정렬하도록 했다.

 

from collections import Counter

array = Counter(num_list)  
most = array.most_common()

print(most[0][0])

 

 

이렇게만 하면 오류가 난다.

 

최빈값 갯수가 같은 값이 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다. 이 조건을 안넣었음

most_common이 갯수를 세어 정렬하면서 작은 수부터 정렬해주므로 -1 이 출력되는 조건문을 만들어준다.

 

most = array.most_common()
# print(most)  [(-2, 2), (-1, 2), (-3, 1)]

if most[0][1] == most[1][1]:
    print(most[1][0])
else:
    print(most[0][0])

 

 

 

 

그리고 이 조건만을 입력하면

array 길이가 1인 경우 most[1]의 값이 없어서 list out of range 오류가 나므로  len()함수로 걸러주어야 한다.

 

if len(array) == 1:
    print(most[0][0])    
elif most[0][1] == most[1][1]:
    ...

 

+ 사족 +

더보기
최빈값.......... 조건을 잘보자.... index에러 뼈아픔

 

 

 

 

 

 

- 과정3 - 범위

 

num1 = 0
for num1 in range(num_list[0], num_list[-1]):
    num1 = int(num1)
print(num1)

 

이런식으로 최종값을 뽑아보려고 했는데

for문이 시간복잡도에 영향을 주므로 조금 더 가벼운 방법을 추천받았다.

 

 

 

범위란 N개의 수들 중 최댓값과 최솟값의 차이

그러므로 최댓값과 최솟값을 빼주기만 하면 되는 것이었다!

 

# print(f"최소값: {num_list[0]}") #-1
# print(f"최댓값: {num_list[-1]}") #3

num = num_list[-1] - num_list[0] 
print(num)

 

 

 

 


 

 

새롭게 알게된 점 : 

 

반올림함수 round(),    사사오입 법칙인척하는 함정카드를 가지고 있다.

 

round(3.5)  # 결과 : 4
round(4.5)  # 결과 : 4

???

 

 

 

 

보통 생각하는 반올림 결과는

3.5 => 4

4.5 => 5

가 되는 결과일텐데,

 

python에서의 round는 정수 부분이 짝수면 반내림이 되고, 홀수면 반올림해준다

 

 

**사사오입의 정확한 의미는 4이하일때는 버리고 5이상이면 올림해주는 것을 말하지만

   외우기 쉽게 round는 사사오입 법칙(짝수일땐 버리고, 홀수일땐 올리고라고 생각)이라고 기억하자...

 

 

 

 

 

- 이 문제를 해결하기 위한 2가지 방법

 

1. 반올림 함수를 새로 구현

2. 짝수일 경우 0.1을 더하여 round 함수를 사용

 

 

+++ numpy 모듈에서의 반올림 +++

np.around(data) : 소수점 자리 수를 반올림해서 정수로 만들어줌
np.round(data, decimals) : 원하는 소수점 자리수에서 반올림

오사오입(round-to-nearest-even)

반올림에서 5 미만의 숫자는 내림, 5 초과의 숫자는 올림합니다.
5의 앞자리가 홀수인 경우에는 올림을, 짝수인 경우에는 내림을 합니다

 

 

 

 

 

이해를 돕기위한 광기의 출력

print(
round(3.4),  # 3
round(3.5),  # 4
round(3.6),  # 4

round(4.4),  # 4
round(4.5),  # 4   <= 이 부분을 주의해야한다
round(4.6),  # 5

round(5.5),  # 5
round(6.5),  # 6   <= ``
sep="\n")

 

 

 

 

+++ 추가

반올림round()함수, 올림은 ceil() 함수, 내림은 floor()함수

 

 

 

 

tmi: C/C++/JavaScript 에서는 반올림이  구동된다고 한다^^..

 

[참조] :  https://cocoze.tistory.com/79