sm 기술 블로그

83. 2108(통계학) 본문

문제/백준_파이썬

83. 2108(통계학)

sm_hope 2022. 6. 13. 22:28
import sys
input = sys.stdin.readline

N = int(input())
num = sorted([int(input())for _ in range(N)])

# 산술평균
avg = sum(num)/N
if -1 < avg < 0:
    print(0)
else:
    print(round(avg))
# 중앙값
midValue = num[N//2]
if -1 < midValue < 0:
    print(0)
else:
    print(midValue)

# 최빈값
max = 0
arr = [-1]*8001
cnt = 0
arr_repo = []
find_max = 0

if(len(num) == 1):
    print(num[0])
else:
    for i in num:
        arr[i+4000] += 1

    for i in range(8001):
        if(arr[i] > find_max):
            arr_repo.clear()
            cnt = 0
            find_max = arr[i]
            max = i-4000
            arr_repo.append(max)
            continue

        if(arr[i] == find_max):
            cnt += 1
            arr_repo.append(i-4000)
            continue

    if(cnt >= 1):
        print(sorted(arr_repo)[1])  # 최빈값 여러개면 두번째로 작은 수
    else:
        print(max)

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

문제요약

산술 평균 : N개의 수들의 합을 N으로 나눈 값
중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 중앙에 위치하는 값
최빈값 : N개의 수들 중 가장 많이 나타나는 값 (같은게 두 개 이상 있으면 작은 값중 두번째)
범위 : N개의 수들 중 최댓값과 최솟값의 차이  를 구하라

해설

자 코드가 엄청 길다.

파이썬 내부 함수중에 위에 네개를 쉽게 구할 수 있는 함수가 있다.

근데 쓰고 싶지 않았다.(자존심이 허락하지 않았다.)

 

그래서 직접 구현하는데 최빈값이 애를 많이 먹었다.

설명 들어간다.

# 산술평균
avg = sum(num)/N
if -1 < avg < 0:
    print(0)
else:
    print(round(avg))
# 중앙값
midValue = num[N//2]
if -1 < midValue < 0:
    print(0)
else:
    print(midValue)
# 범위
print(num[len(num)-1]-num[0])

산술 평균, 중앙값, 범위는 어렵지 않을 것이다.

산술평균과 중앙값에서

주의 해야 할 점은 음수인데 만약 -0.333 이 나오면 -0이나 -1이 나오면 안된다. (그냥 //를 사용하면 -1이 나옴)

따라서 -1 ~ 0은 0이 나오도록 처리해주었다.

# 최빈값
max = 0
arr = [-1]*8001
cnt = 0
arr_repo = []
find_max = 0

if(len(num) == 1):
    print(num[0])
else:
    for i in num:
        arr[i+4000] += 1

    for i in range(8001):
        if(arr[i] > find_max):
            arr_repo.clear()
            cnt = 0
            find_max = arr[i]
            max = i-4000
            arr_repo.append(max)
            continue

        if(arr[i] == find_max):
            cnt += 1
            arr_repo.append(i-4000)
            continue

    if(cnt >= 1):
        print(sorted(arr_repo)[1])  # 최빈값 여러개면 두번째로 작은 수
    else:
        print(max)

먼저 값이 하나면 그냥 자신을 출력해주면 된다.

 

카운팅 정렬에서 영감을 얻어 카운팅 정렬과 비슷한 방법을 사용하였다.

 if(arr[i] > find_max):
            arr_repo.clear()
            cnt = 0
            find_max = arr[i]
            max = i-4000
            arr_repo.append(max)
            continue

일단 arr_repo.append(max)를 사용한 이유는 제일 많이 나온 수라고 생각한 수와 빈도 수가 같고 그 이상의 수가 없는 경우가 있다.

 

예를 들어 1 1 2 3 3 에서 1과 3은 빈도수가 같다.

일단 배열 특성상 1이 먼저 최고 값으로 들어간다.

arr_repo를 선언하지 않는다면 1이 최고구나 하고 끝이다.

1과 같은 수 3이 들어와도 얘는 최고구나 하고 저장해서 처리가 불가능 하다.

따라서 똑같은 수가 나올 수 있기 때문에 append로 추가해주었다.

 

근데 clear는 왜 했느냐

만약 1 1 2 2 2 가 있다.

처음에는 1이 최빈값이여서  위와 같이 저장 하였다.

근데 2가 더 빈도수가 높다.

따라서 1은 지워줘야 한다.

 

   if(arr[i] == find_max):
            cnt += 1
            arr_repo.append(i-4000)
            continue

    if(cnt >= 1):
        print(sorted(arr_repo)[1])  # 최빈값 여러개면 두번째로 작은 수
    else:
        print(max)

최빈값이 만약 같다면 arr_repo에 저장해둔다.

cnt가 1이라는 것은 최빈값이 같은 게 하나 이상 있다는 것이다.

따라서 같은 최빈값들 중에서 두번째로 작은 수를 출력해야한다.

두번 째 작은 수를 출력하는 방법은 오름차순으로 정렬을 하고 1번째 (첫번째 아님) 인덱스 값을 출력해주면 된다.

 

 

'문제 > 백준_파이썬' 카테고리의 다른 글

85. 11650(좌표 정렬하기)  (0) 2022.06.15
84. 1427(소트인사이드)  (0) 2022.06.14
82. 10989(수 정렬하기3)  (0) 2022.06.13
81. 2751 (수 정렬하기 2)  (0) 2022.06.13
80. 2750(수 정렬하기)  (0) 2022.06.12
Comments