[BaekJoon]2108번: 통계학
❓문제
수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다.
단, N은 홀수라고 가정하자.
산술평균 : N개의 수들의 합을 N으로 나눈 값
중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
최빈값 : N개의 수들 중 가장 많이 나타나는 값
범위 : N개의 수들 중 최댓값과 최솟값의 차이
N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.
✏️입력
첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.
📜출력
첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.
둘째 줄에는 중앙값을 출력한다.
셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.
넷째 줄에는 범위를 출력한다.
💻코드
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int whatIsMode(const int arr[], int len) {
int tmp[8001] = { 0 };
int max, cnt = 0;
int mode;
//tmp의 인덱스 = arr의 숫자
//tmp 값 = 개수
for (int i = 0; i < len; i++) {
tmp[arr[i] + 4000]++;
}
max = *max_element(tmp, tmp + 8001);
for (int i = 0; i < 8001; i++) {
if (tmp[i] == max) {
cnt++; //가장 큰 값이 나온 횟수를 올려준다. 두번째값을 구해야하므로
mode = i - 4000;
if (cnt == 2) {
break;
}
}
}
return mode;
}
int main(void) {
int N;
cin >> N;
double sum = 0;
int mean; //평균
int median, mode, distance; //중앙값, 최빈값, 범위
int* arr = new int[N];
//배열 값 입력받기
for (int i = 0; i < N; i++) {
cin >> arr[i];
sum += arr[i]; //값의 합
}
mean = round(sum / N); //평균
sort(arr, arr + N); //배열 정렬
distance = arr[N - 1] - arr[0]; //범위
median = arr[(N-1) / 2]; //중앙값 0~N-1중 가운데값 (N은 홀수)
mode = whatIsMode(arr,N); //최빈값
cout << mean << "\n";
cout << median << "\n" << mode << "\n" << distance << "\n";
delete[]arr;
return 0;
}
-
최빈값을 구하는 과정이 어려웠다.
개수가 같으면 두번째로 작은 수를 구해야 하는 조건때문에 더 까다로웠던 것 같다. 처음에는 for문을 돌면서 옆에 붙어있는 숫자끼리 비교하려 했는데 이 방법으로는 두번째로 작은 최빈값을 구하기 어려워 포기했다. 따라서 정수 범위(-4000~4000)를 크기로 하는 배열을 하나 만들어 값의 개수를 배열에 넣었다. 배열의 인덱스가 입력받은 값이 되는 것이고 for문을 돌리면서 해당 인덱스 배열 값을 하나씩 증가시킨다. 그리고 이 배열의 최대값을max_element()
함수로 구하고 다시 for문을 돌리면서 최대값을 갖는 인덱스를 찾는다. -
round() 반올림 함수
처음에는cout<<fixed;
cout.precision(0);
으로 반올림 할 수 있다고 생각했는데, 예제 4번(3,0,0,-1)을 집어넣는 경우 평균이 0이 아닌-0
이 나온다. 따라서 round()함수로 반올림 해주었다. -
float가 아니라 double
sum을 float 형으로 선언했었는데, double로 해주니 바로 해결되었다.
sum의 최대값은 4000*500000 인데, float은 8자리까지가 최선이므로 잘릴 수 있다. 따라서 double을 사용해야한다.