개발 지식 공유, 복습

백준 - 2108(통계학) C++ 본문

알고리즘(백준)

백준 - 2108(통계학) C++

like_sonny 2021. 12. 21. 01:17

https://www.acmicpc.net/problem/2108

 

2108번: 통계학

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

www.acmicpc.net

이번 문제는 N개의 수가 주어졌을 때 산술평균, 중앙값, 최빈값, 범위를 구해야 한다.

  1. 산술평균 : N개의 수들의 합을 N으로 나눈 값
  2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
  3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값
  4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이

1. 평균은 입력받은 값들을 다 더해 데이터 개수로 나누면 된다.

2. 중앙값은 받은 데이터들을 오름차순으로 정렬한 후, 전체 데이터의 수를 반으로 한 인덱스로 지정하면 중앙값이다.

3. 범위는 algorithm 헤더에 max_element, min_element를 사용하면 배열에서 가장 최댓값과 최솟값을 구할 수 있어 이의 차를 계산하면 된다.

 

사용법은 다음과 같다.

// 배열 이름은 arr로 가정
// 최댓값
#include <algorithm>
int max = *max_element(arr, arr + n)
// 최솟값
int min = *min_element(arr, arr + n)

4. 최빈값을 생각하는데 조금 오래 걸렸다. 그 이유는 

셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다. 

과 같은 조건이 있었기 때문이다.

 

그래서 필자는 한 배열의 크기를 8000으로 설정하고 입력되는 데이터에 4000을 더해 해당 수의 인덱스를 하나씩 증가시켰다.이렇게 4000을 더한 이유는 음수인 데이터는 인덱스를 지정할 수 없기 때문이다.

 

가장 많이 나타나는 수를 max, 그 인덱스를 res로  두고 이와 같으면 cnt값을 증가시키고 이보다 더 큰 값을 max로 두고 해당 인덱스를 res, cnt를 다시 0으로 초기화하는 식으로 반복했다.

 

결과 코드이다.

#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;

int main()
{
  freopen("input.txt", "rt", stdin);
  int n;
  scanf("%d", &n);
  int arr[n];
  int arr2[8001] = {0};
  int data;
  double sum = 0;
  for (int i = 0; i < n; i++)
  {
    scanf("%d", &data);
    arr[i] = data;
    // 데이터를 입력받으면서 더했다.
    sum += arr[i];
    // 음수가 있으므로 4000을 더해줘 저장했다.
    // 음수 인덱스는 없으므로!
    arr2[data + 4000]++;
  }

  int cnt;
  // 가장 많이 나타난 수
  int max = 0;
  int i;
  // 가장 많이 나타난 수의 인덱스
  int res;
  for (i = 0; i < 8001; i++)
  {
    if (arr2[i] > max)
    {
      max = arr2[i];
      res = i;
      cnt = 0;
    }
    else if (arr2[i] == max)
    {
      cnt++;
      if (cnt == 1)
      {
        max = arr2[i];
        res = i;
      }
      else if (cnt > 1)
        continue;
    }
  }
  // 다시 원래 수로 복구하기 위해 4000을 뺀다.
  int always = res - 4000;

  sort(arr, arr + n);
  int avg = round(sum / n);

  int center = arr[n / 2];

  int range = *max_element(arr, arr + n) - *min_element(arr, arr + n);

  printf("%d\n%d\n%d\n%d\n", avg, center, always, range);
  return 0;
}

통과 기록