문제 링크: https://www.acmicpc.net/problem/2108
이 문제를 풀기 위해 우선 문제를 분석해 보겠습니다.
문제 개요
- N개의 수가 주어졌을 때, 다음 네 가지 통계값을 구하는 프로그램을 작성해야 합니다.
- 산술평균
- 중앙값
- 최빈값
- 범위
입력
- 첫째 줄에 수의 개수 N (1 ≤ N ≤ 500,000)이 주어집니다.
- 수가 큰 만큼 input() 함수를 재정의 하도록 하겠습니다.
- N은 홀수입니다.
- 중앙값을 계산하기 편리하게 하기 위해 N의 값을 홀수로 지정한 것 같습니다.
출력
- 네 가지 통계값을 각각 한 줄에 하나씩 출력해야 합니다.
- 그냥 print() 함수를 여러 번 사용하기보다 sep="\n"을 사용해서 한 번에 작성하겠습니다.
세부 요구사항
- 산술평균: N개의 수들의 합을 N으로 나눈 값을 첫째 자리에서 반올림하여 출력해야 합니다.
- round() 함수를 사용해서 해결해 보겠습니다.
- 중앙값: N개의 수들을 증가하는 순서로 나열했을 때 그 중앙에 위치하는 값을 출력합니다.
- N의 값이 짝수이므로 '요소의 개수//2'를 통해 해당 인덱스를 찾아내겠습니다.
- 최빈값: 가장 많이 나타나는 값을 출력합니다. 여러 개 있을 때는 최빈값 중 두 번째로 작은 값을 출력합니다.
- 범위: N개의 수들 중 최댓값과 최솟값의 차이를 출력합니다.
아래는 전체 코드입니다.
import sys
input = sys.stdin.readline
N = int(input())
data = [int(input()) for _ in range(N)]
data.sort()
def arithmetic_mean(data):
result = round(sum(data)/len(data))
return result
def center(data):
result = data[len(data)//2]
return result
def mode(data):
stack = {}
for num in data:
if num in stack:
stack[num] += 1
else:
stack[num] = 1
max_stack = max(stack.values())
result = sorted([num for num, stack in stack.items() if stack == max_stack])
return result[1] if len(result) > 1 else result[0]
def data_range(data):
result = max(data) - min(data)
return result
print(arithmetic_mean(data),
center(data),
mode(data),
data_range(data),
sep='\n')
코드를 한 번 분석해 보겠습니다.
- 입력 처리 및 데이터 준비
import sys input = sys.stdin.readline N = int(input()) data = [int(input()) for _ in range(N)] data.sort()
- sys.stdin.readline을 사용하여 input() 함수를 재정의 합니다. 이는 대량의 입력을 처리할 때 매우 효과적입니다.
- 리스트 컴프리헨션을 사용하여 N개의 정수를 입력받아 data 리스트에 저장합니다.
- data.sort()로 리스트를 정렬합니다. 중앙값과 최빈값 계산에서 사용합니다.
- 산술평균 계산
def arithmetic_mean(data): result = round(sum(data)/len(data)) return result
- sum(data)를 이용하여 모든 값의 합을 구하고 데이터의 요소의 개수만큼 나누어 평균을 계산합니다.
- round() 함수를 사용하여 첫째 자리에서 반올림합니다.
- 중앙값 계산
def center(data): result = data[len(data)//2] return result
- 이미 오름차순으로 정렬된 리스트에서 중앙에 위치한 값을 반환합니다.
- N이 홀수이므로 len(data)//2로 중앙 인덱스를 계산할 수 있습니다.
- 최빈값 계산
def mode(data): stack = {} for num in data: if num in stack: stack[num] += 1 else: stack[num] = 1 max_stack = max(stack.values()) result = sorted([num for num, stack in stack.items() if stack == max_stack]) return result[1] if len(result) > 1 else result[0]
- 빈 딕셔너리 stack을 사용해서 각 숫자의 빈도수를 계산합니다.
- 나중에 in을 사용하기 때문에 시간 복잡도가 적은 딕셔너리를 사용했습니다.
- key는 data의 요소이고, value는 빈도수입니다.
- data 리스트의 각 숫자에 num에 대해:
- 이미 stack에 있으면 빈도수를 1 증가시킵니다.
- 없으면 새로 추가하고 빈도수를 1로 설정합니다.
- max(stack.value())로 최대 빈도수를 찾습니다.
- 리스트 컴프리헨션으로 최대 빈도수를 가진 숫자들을 추출하고 정렬합니다.
- stack.items()로 (숫자, 빈도수) 쌍을 반환합니다.
- num은 숫자(키), stack은 빈도수(값)입니다.
- 빈도수가 max_stack과 같은 숫자들만 선택합니다.
- 조건을 만족하는 숫자(num)만을 선택하여 새 리스트를 생성합니다.
- sorted([...])를 사용하여 선택된 숫자들로 구성된 리스트를 오름차순으로 정렬합니다.
- 최빈값이 여러 개(길이가 1보다 큼)인 경우 두 번째로 작은 값을 반환합니다.
- 빈 딕셔너리 stack을 사용해서 각 숫자의 빈도수를 계산합니다.
- 범위 계산
def data_range(data): result = max(data) - min(data) return result
- 리스트의 특성을 활용하여 최댓값에서 최솟값을 뺍니다.
- 결과 출력
print(arithmetic_mean(data), center(data), mode(data), data_range(data), sep='\n')
- print() 함수의 sep 매개변수를 사용해서 코드를 더 간결하게 만듭니다.
# 이 글의 내용 중 일부는 Perplexity AI의 도움을 받아 정보를 수집하고 정리하였으며, 추가적인 연구와 개인적인 견해를 더하였습니다.
'백준 문제풀이' 카테고리의 다른 글
[백준] 10825번 국영수 - Python(1편) (1) | 2024.12.12 |
---|---|
[백준] 11656 접미사 배열 - Python(1편) (0) | 2024.12.11 |
[백준] 10815번 숫자 카드 - Python(1편) (0) | 2024.12.10 |
[백준] 1764번 듣보잡 - Python (0) | 2024.12.10 |
[백준] 10816번 숫자 카드 2 - Python (3) | 2024.12.10 |