이 문제도 순탄하게 네 가지 기능 다 처리할 수 있을 줄 알았는데, 세 번째 기능인 최빈값(mode) 구하는 과정을 구성하는 것이 다소 까다로웠다. 아래는 내가 처음에 작성했던 최빈값 코드
def mode():
arr = [0]*(max(data)+1) # 숫자 출연 횟수 리스트 (이 리스트의 인덱스i 가 출연 숫자와 동일함)
for i in data:
arr[i] += 1
modes = [i for i, c in enumerate(arr) if c == max(arr)] # i는 인덱스이자 출연 숫자를 의미, c는 해당 숫자의 출현 횟수
if len(modes) > 1:
# 최빈값이 여러 개일 경우 두 번째로 작은 값 반환
modes.sort()
return modes[1]
else:
return modes[0]
위 코드는 arr = [0]*(max(data)+1) 에서 리스트의 길이를 데이터의 최댓값에 맞춰 설정하여 이를 토대로 각 숫자마다 대응되는 리스트 위치에 숫자 출연 횟수를 기록하는 방식으로 작성한 것이다.
<예시>
입력값인 data : [1, 2, 2, 2, 3, 3, 4]
인 경우 여기서 max(data)는 4이므로 arr의 길이는 5가 되어 다음과 같이 생성된다.
arr = [0, 0, 0, 0, 0]
여기에 for문을 통해 data 리스트에서 숫자가 등장할 때마다 arr에 대응하는 위치에 1을 증가시키도록 하면 다음과 같다.
arr = [0, 1, 3, 2, 1] (1이 1개, 2가 3개, 3이 2개, 4가 1개)
여기서 max(arr)은 max(data)와 달리 최다 출현 빈도수인 3이 되므로, 최빈값인 3이 출력되게 되는 원리이다.
그런데 이렇게 해서 제출했을때 틀렸다고 나왔는데, 확인해보니 위 함수는 양수만 처리하며 음수값을 제대로 처리해내지 못하고 있었기 때문이다. 음수 인덱스를 리스트에서 사용할 수 없으므로, 음수와 양수 모두를 처리할 수 있도록 수정이 필요했음
분석해보니 사실상 원인은 max(data) 이므로, 이를 데이터의 최소값과 최대값을 사용해 리스트 크기를 결정할 수 있도록 다음과 같이 수정하였다.
<최종 정답 코드>
import sys
def arithmetic():
return round(sum(data)/len(data))
def median():
lst = sorted(data, reverse=False)
k = N//2-1
if N % 2 == 0 : # 길이가 짝수인 경우
return (lst[k] + lst[k+1])/2
else:
return lst[k+1]
def mode():
max_val = max(data)
min_val = min(data)
arr = [0]*(max_val-min_val+1) # 숫자 출연 횟수 리스트 (이 리스트의 인덱스i 가 출연 숫자와 동일함)
for i in data:
arr[i - min_val] += 1
modes = [i+min_val for i, c in enumerate(arr) if c == max(arr)] # i는 인덱스이자 출연 숫자를 의미, c는 해당 숫자의 출현 횟수
if len(modes) > 1:
# 최빈값이 여러 개일 경우 두 번째로 작은 값 반환
modes.sort()
return modes[1]
else:
return modes[0]
def scope():
return (max(data)-min(data))
N = int(input())
put = sys.stdin.read()
data = list(map(int, put.split()))
print(arithmetic())
print(median())
print(mode())
print(scope())
추가로 소수점 반올림 구현은 round() 함수로 처리하였다.
처음엔 문제에서 주어진 예시가 모두 올바르게 돌아가는 걸 확인했음에도 위 코드가 시간 초과 오류로 틀렸다고 떴었다.
시간 초과 안뜨게 하려고 일부러 sys.stdin.read()도 했는데..
비효율적인 부분을 살펴보다가 median 함수와 mode 함수에서 max(), min(), len() 함수를 사용하는 경우마다 변수를 생성하여 사용하지 않고 매번 호출하는 구조로 사용하다 보니까 시간 초과가 뜬 것 같다고 판단하였다.
따라서 이를 모두 max_val = max(data) 이런 식으로 변수화해주고, 생성한 변수를 프로그램 내에서 사용하도록 변경하였더니 시간 초과 오류가 해결되어 성공할 수 있었음!
from collections import Counter
def mode():
counts = Counter(data)
max_count = max(counts.values())
modes = [num for num, count in counts.items() if count == max_count]
if len(modes) > 1:
return min(modes)
else:
return modes[0]
참고로 파이썬의 장점인 라이브러리를 위와 같이 사용할수도 있었지만, (심지어 mode 함수 자체도 이미 있음) 이는 파이썬만 가능한거기도 하고 문제를 푸는 의미가 없기에... 최대한 하드코딩으로 풀어보려고 노력하였다.
위 코드는 Counter를 사용해서 각 숫자의 출현 빈도를 효율적으로 계신한 뒤 최빈값을 출력해준다.
'Python' 카테고리의 다른 글
[백준/Python] 1920 : 수 찾기 (0) | 2024.09.15 |
---|---|
[백준/Python] 2751 : 수 정렬하기 2 (0) | 2024.09.15 |
[백준/Python] 1181 : 단어 정렬 (0) | 2024.09.15 |
[백준/Python] 26215 : 눈 치우기 (0) | 2024.09.08 |
[백준/Python] 1213 : 펠린드롬 만들기 (0) | 2024.09.08 |