종식당

[백준 2108] 통계학 본문

백준

[백준 2108] 통계학

종식당 2024. 1. 19. 15:18
728x90
반응형

 

이번 문제에서 크게 어려운 점은 없었지만 짚고 넘어가야 할 것은 round() 함수와 collections모듈의 Counter클래스의 사용법이다.

처음에 이 문제를 풀 때 신경쓰였던 점은 최빈값을 구하는 점이었다. 그래도 이전에 프로그래머스에서 최빈값 관련 문제를 풀어본 적이 있어서 풀긴 했지만 시간초과가 나버렸다. 다음은 처음 시간초과가 난 코드이다.

import sys
input = sys.stdin.readline

N = int(input())
answer = []
lst = [input().rstrip() for i in range(N)]
lst = list(map(int,lst))
sort_lst = sorted(lst)
k = []

answer.append(int(round(sum(lst)/len(lst),0)))#산술평균

answer.append(sort_lst[int(len(lst)/2)])#중앙값

max = 0
for i in lst:
    result = lst.count(i)
    if result > max:
        max = result

for i in lst: #최빈값
    if lst.count(i) == max:
        k.append(i)
k.sort(reverse=True)
if len(k) == 1:
    answer.append(k[0])
else:
    answer.append(k[-2])

answer.append(sort_lst[-1]-sort_lst[0])#범위

for i in answer:
    print(i)

 

그리고 글을 적으면서 생각난 점인데 블로그 첫 문제에서 입력을 받을 때는 시간 처리가 빠른 sys.stdin.readline을 사용해야 겠다고 생각했었다. 근데 그 이후로 많은 문제들을 풀면서 또 느낀 건데 readline을 쓰려면 strip()의 사용법도 정확히 숙지하고 이를 빼먹으면 안 되겠다고 생각했다. 

sys.stdin.readline 말고 그냥 sys.stdin.readlines도 있는데 얘는 한 줄씩 입력받지 않고 전체를 입력받아 각 줄이 개행이 포함되어 리스트에 저장된다고 한다. 알아두자!

 

다시 문제로 돌아와서 먼저 산술평균을 구할 때 반올림 하기 위해서 round()함수를 사용했는데 round() 함수의 사용법에 대해 알아보겠다.

  •  round(num1,num2)

먼저 첫 번째 인자로 반올림하려는 숫자를 넣고 두 번째 인자에 몇째 자리까지 표현하고 싶은 지 넣어주면 된다. 

예를 들어 round(3.14,1) 이런 식으로 사용하면 3.1을 출력한다. 위에서는 정수자리만 뽑고 싶어 저렇게 표현했는데 저러지 말고 두 번째 인자를 그냥 쓰지 않으면 정수 부분만 나온다고 한다!

 

중앙값과 범위를 구하는 부분은 너무 간다 해서 넘어가고 다음으로 최빈값에 대해 살펴보겠다.

먼저 처음 생각한 방법은 lst에서 각각의 숫자의 count를 구해서 max count가 몇인지 구했다. 그리고 다시 for문을 돌려 max count만큼의 개수가 있는 숫자가 무엇인지 찾아 이들만 새로 리스트를 만들어 주어 여기서 구하려고 했는데 count()이 부분에서 시간초과가 난 것 같다.

 

그래서 Counter를 사용하였다. 일단 Counter를 사용하기 위해서는  from collections import Counter를 이용해야 한다.

아직 모듈의 클래스를 import 하는 부분이 어색한 느낌인데 from 모듈 import 클래스 이를 기억해야 할 것 같다.

Counter를 통해 리스트를 넘기면 각 원소가 몇 번씩 나오는지 저장된 객체를 얻을 수 있다. 다음은 Counter의 사용법이다.

 

>>> Counter(["hi", "hey", "hi", "hi", "hello", "hey"])
Counter({'hi': 3, 'hey': 2, 'hello': 1})

 

>>> Counter("hello world")
Counter({'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1})

 

def countLetters(word):
    counter = {}
    for letter in word:
        if letter not in counter:
            counter[letter] = 0
        counter[letter] += 1
    return counter

countLetters('hello world'))
{'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}

 

다음으로 Counter클래스의 most_common() 메서드이다. 이를 사용하면 데이터의 수가 가장 많은 순으로 리스트를 반환한다.

from collections import Counter

Counter('hello world').most_common()
[('l', 3), ('o', 2), ('h', 1), ('e', 1), (' ', 1), ('w', 1), ('r', 1), ('d', 1)]

 

이때 most_common()의 인자로 n개를 넘기면 가장 개수가 많은 n개의 데이터를 반환한다.

from collections import Counter

Counter('hello world').most_common(1)
[('l', 3)]

 

다음은 counter.values()와 counter.items()에 대해 알아보겠다.

counter = Counter({1: 2, 2: 3, 3: 1})
values = counter.values()
print(values)

dict_values([2, 3, 1])

 

counter = Counter({1: 2, 2: 3, 3: 1})
items = counter.items()
print(items)

dict_items([(1, 2), (2, 3), (3, 1)])

 

max( counter.values())를 이용해서 먼저 max count를 구하고 counter.items()를 이용해서 max count의 개수만큼 있는 데이터들을 따로 mode_values리스트에 넣어주었다. 그리고 이 리스트 안에서 최빈값 조건을 처리하였다.

최빈 값 관련 문제가 나왔을 때는 꼭 collections모듈의 Counter클래스를 기억하면 유용할 것 같다.

 

제출 코드

import sys
from collections import Counter

input = sys.stdin.readline

N = int(input())
answer = []
lst = [int(input().rstrip()) for _ in range(N)]

# 산술평균
answer.append(int(round(sum(lst) / len(lst), 0)))

# 중앙값
sort_lst = sorted(lst)
answer.append(sort_lst[N // 2])

# 최빈값
counter = Counter(lst)
max_count = max(counter.values())
mode_values = [num for num, count in counter.items() if count == max_count]
mode_values.sort(reverse=True)
answer.append(mode_values[0] if len(mode_values) == 1 else mode_values[-2])

# 범위
answer.append(sort_lst[-1] - sort_lst[0])

for i in answer:
    print(i)
728x90
반응형

'백준' 카테고리의 다른 글

[백준 20291] 파일 정리  (0) 2024.02.01
[백준 1755] 숫자놀이  (3) 2024.01.31
[백준 10814] 나이 순 정렬  (2) 2024.01.31
[백준 10845] 큐  (0) 2024.01.17
[백준 2075] N번째 큰 수  (1) 2024.01.16