2 minute read

❓문제

수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 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;

    }
  1. 최빈값을 구하는 과정이 어려웠다.
    개수가 같으면 두번째로 작은 수를 구해야 하는 조건때문에 더 까다로웠던 것 같다. 처음에는 for문을 돌면서 옆에 붙어있는 숫자끼리 비교하려 했는데 이 방법으로는 두번째로 작은 최빈값을 구하기 어려워 포기했다. 따라서 정수 범위(-4000~4000)를 크기로 하는 배열을 하나 만들어 값의 개수를 배열에 넣었다. 배열의 인덱스가 입력받은 값이 되는 것이고 for문을 돌리면서 해당 인덱스 배열 값을 하나씩 증가시킨다. 그리고 이 배열의 최대값을 max_element()함수로 구하고 다시 for문을 돌리면서 최대값을 갖는 인덱스를 찾는다.

  2. round() 반올림 함수
    처음에는 cout<<fixed; cout.precision(0);으로 반올림 할 수 있다고 생각했는데, 예제 4번(3,0,0,-1)을 집어넣는 경우 평균이 0이 아닌 -0이 나온다. 따라서 round()함수로 반올림 해주었다.

  3. float가 아니라 double
    sum을 float 형으로 선언했었는데, double로 해주니 바로 해결되었다.
    sum의 최대값은 4000*500000 인데, float은 8자리까지가 최선이므로 잘릴 수 있다. 따라서 double을 사용해야한다.