[백준] 2108번 : 통계학

letsbebrave·2022년 2월 24일
1

codingtest

목록 보기
28/146

문제

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

개념

처음 풀 때 시간초과가 떴다.
그 해결책은

  1. sys.stdin.readline()
  2. collections 모듈의 Counter 클래스로 최빈값 구현

sys.stdin.readline()

반복문으로 여러줄 입력받는 상황에서는 반드시 sys.stdin.readline()을 사용해야 시간초과가 발생하지 않는다!

문자열을 입력받을 때

개행문자(\n)가 기본으로 추가된다

import sys

sen = sys.stdin.readline()

한 개의 정수 입력받을 때

sys.stdin.readline()의 return 값은 문자열(string)이므로 정수로 입력받으려면 형변환을 해줘야 함
이때는 개행문자는 사라지고 정수형태만 남는다

import sys

sen = int(sys.stdin.readline())

정해진 개수의 정수를 한줄에 입력받을 때

import sys
a,b,c = map(int,sys.stdin.readline().split())

임의의 개수의 정수를 한줄에 입력받아 리스트에 저장할 때

중요한 점은 위에서 변수에 각각 저장해준 것과 달리, 리스트 변수에 값을 저장해주는 것이다!!

import sys
data = list(map(int,sys.stdin.readline().split()))

문자열 n줄을 입력받아 리스트에 저장할 때

strip()을 가지고 문자열 맨 앞과 맨 끝의 공백문자를 제거해준다.

import sys
n = int(sys.stdin.readline())
data = [sys.stdin.readline().strip() for i in range(n)]

참고사이트 :
https://growingarchive.tistory.com/157

https://velog.io/@yeseolee/Python-파이썬-입력-정리sys.stdin.readline

collections 모듈의 Counter 클래스로 최빈값 구현

Counter(리스트)

Counter는 사전(dict) 클래스의 하위 클래스로 리스트나 튜플에서 각 데이터가 등장한 횟수를 사전 형식으로 돌려줌

from collections import Counter 
colors = ['red', 'blue', 'red', 'green', 'blue', 'blue'] 
cnt = Counter(colors)
# cnt 출력 시 Counter({'blue': 3, 'red': 2, 'green': 1})

Counter(리스트).most_common()

등장한 횟수만 내림차순으로 정리하여 다음과 같이 보여준다.
만약 등장한 횟수가 같은 수들은 임의의 순서로 정렬된다!! (등장 횟수만 내림차순으로 정렬됨)

from collections import Counter 
cnt = Counter(num)
mode = cnt.most_common()
# Counter({1: 1, 3: 1, 8: 1, -2: 1, 2: 1})
# cnt.most_common() 출력 시 (등장횟수만 내림차순이고 앞의 수는 정렬 안 됨)
# [(1, 1), (3, 1), (8, 1), (-2, 1), (2, 1)]
# [(3, 2), (1, 2), (5, 1)]

만약 상위 3개의 결과만을 원한다면

cnt.most_common(3) [(4, 3), (3, 2), (5, 2)]

최빈값 얻어내고 싶다면

mode = cnt.most_common(1)
mode
[(4, 3)]
mode[0][0]
4

참고사이트:
https://codepractice.tistory.com/71

첫번째 풀이 (시간초과)

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

# TypeError: 'int' object is not iterable
# 정수 자체는 반복할 수 없음
# for 변수 in 리스트(또는 튜플, 문자열):

for i in range(N):
    num.append(int(input()))

# 산술평균
# 소수 첫째 자리에서 반올림 round(숫자)
print(round(sum(num) / N))

# 중앙값
sortedlist = sorted(num)
print(sortedlist[(N-1)//2])

# 최빈값
countlist = []

for i in num:
    countlist.append(num.count(i))
    
maxnum = max(countlist)

maxlist= []
for i in range(len(countlist)):
    if countlist[i] == maxnum:
        maxlist.append(num[i])

if len(list(set(maxlist))) >= 2:
    # set()함수로 중복제거 -> 리스트 만들기 -> 오름차순정렬
    maxlist = sorted(list(set(maxlist)))
    print(maxlist[1])
else:
    print(maxlist[0])
    
# 범위
print(sortedlist[N-1]- sortedlist[0])
    

정답 풀이

from collections import Counter
import sys

N = int(sys.stdin.readline())
num = []

# TypeError: 'int' object is not iterable
# 정수 자체는 반복할 수 없음
# for 변수 in 리스트(또는 튜플, 문자열):

for i in range(N):
    num.append(int(sys.stdin.readline()))

# 산술평균
# 소수 첫째 자리에서 반올림 round(숫자)
print(round(sum(num) / N))

# 중앙값
sortedlist = sorted(num)
print(sortedlist[(N-1)//2])

# 최빈값
cnt = Counter(num) # 각 데이터가 등장한 횟수를 딕셔너리 형식으로 보여줌 Counter({1: 2, 3: 1, 5: 1, 2: 1})
mode = cnt.most_common() # 등장 횟수만 내림차순으로 정리하여 보여줌 [(3, 2), (1, 2), (5, 1)]
count = 0

# [(1, 1), (3, 1), (8, 1), (-2, 1), (2, 1)]
# [(-1, 2), (-2, 2), (-3, 1)]
# [(-2, 2), (-1, 2), (-3, 1)]

for i in range(len(mode)):
    if mode[0][1] == mode[i][1]:
        count += 1
modenum = []
if count >= 2:
    for i in range(count):
        modenum.append(mode[i][0])
    modenum = sorted(modenum) # 오름차순 정렬 [-2, 1, 2, 3, 8]
    print(modenum[1])
else:
    print(mode[0][0])



# 범위
print(sortedlist[N-1]- sortedlist[0])
    
profile
그게, 할 수 있다고 믿어야 해

0개의 댓글