컴퓨터기본/문제풀이

[백준] 2108: 통계학

차가운오미자 2021. 9. 6. 18:20

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

 

2108번: 통계학

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

www.acmicpc.net

문제 이해

문제 자체가 어렵다기 보다, 예외적인 경우가 많아서 잘 잡는 게 중요하다. 

 

1. 평균

 입력 받을 때 sum 계산했다가 N으로 나눠서 출력만 해주면 됨

for(int i = 0; i<N; i++)
{
  cin >> arr[i];
  sum += arr[i];
}

printf("%.0f\n", (double)sum/N);

2. 중앙값

  1. 입력을 받을 때마다, lookup table에 입력된 숫자의 카운트를 올려준다. 
  2. 출력할 때는 lookup table의 처음부터 숫자 카운트를 다 더해가면서 N/2보다 크거나 같아지는 순간의 index를 출력해주면 된다. 
int numbers[8000+10]; // lookup table

int main(void){

  int med;	// 중앙값 저장 
  int med_cnt = 0;	// 중앙값 구하기 위한 cnt 

  for(int i = 0; i<N; i++){
    cin >> arr[i];
    numbers[4000+arr[i]]++;
  }
  
  // 중앙값 출력	
  for(int i = 0; i<8005; i++)
  {
    med_cnt += numbers[i];
    if(med_cnt>=N/2+1)
    {
      med = i;
      break; 
    }
  }
  printf("%d\n", med-4000);
}

3. 최빈값 출력

numbers 배열에서 가장 카운트가 큰 값을 저장한다.

만약 여러 개일 수 있으므로 다시 루프를 돌며 그 값을 가진 인덱스 중 두 번째로 작은 애를 프린트한다.

만약 하나이면 하나 그대로 프린트한다. 

	
int main(void){    
  int mode_cnt = 0;	// 최빈값 출력 위한 cnt 
  int mode_i = 0;	// 최빈값인 인덱스(numbers) 
  int max = 0; // 가장 많이 나타난 횟수 
  for(int i = 0; i<8005; i++){
    if(numbers[i] == max){
      mode_i = i;
      mode_cnt++;
    }
    if(cnt >= 2) {
      printf("%d\n", mode_i-4000);
      break;
    }
  }
  if(cnt == 1) printf("%d\n", mode_i-4000);
}

4. 범위 출력

초기값만 주의해주면 된다.

가능한 숫자의 범위가 -4000 ~ 4000 이므로, 

smallest는 4000 초과의 숫자, biggest는 -4000 미만의 숫자로 초기화시키고 해야 한다. 

for(int i = 0; i<N; i++){
  cin >> arr[i];
  if(arr[i]>biggest) biggest = arr[i];
  if(arr[i]<smallest) smallest = arr[i];
}
// 범위 출력 
printf("%d\n", biggest - smallest);

전체 코드

// num2108
#include <iostream>

using namespace std;

int N;
int arr[500000+10];
int numbers[8000+10];

int main(void){
	
	int biggest = -4010;
	int smallest = 4010;
	long long int sum = 0;
	int med;	// 중앙값 저장 
  	int med_cnt = 0;	// 중앙값 구하기 위한 cnt 
	int mode_cnt = 0;	// 최빈값 출력 위한 cnt 
  	int mode_i = 0;	// 최빈값인 인덱스(numbers) 
  	int max = 0; // 가장 많이 나타난 횟수 
	
	cin >> N;
	for(int i = 0; i<N; i++){
		cin >> arr[i];
		sum += arr[i];
		numbers[4000+arr[i]]++;
		if(arr[i]>biggest) biggest = arr[i];
		if(arr[i]<smallest) smallest = arr[i];
	}
	
	// 평균 출력
	printf("%.0f\n", (double)sum/N);
	
    // 중앙값 출력	
	for(int i = 0; i<8005; i++){
		med_cnt += numbers[i];
		if(med_cnt>=N/2+1){
			med = i;
			break; 
		}
	}
	printf("%d\n", med-4000);
	
    // 최빈값 출력
	for(int i = 0; i<8005; i++){
		if(numbers[i]>max){
			max = numbers[i];
		}
	}

	for(int i = 0; i<8005; i++){
		if(numbers[i] == max){
			mode_i = i;
			mode_cnt++;
		}
		if(mode_cnt >= 2) {
			printf("%d\n", i-4000);
			break;
		}
	}
	if(mode_cnt == 1) printf("%d\n", mode_i-4000);
	
	// 범위 출력 
	printf("%d\n", biggest - smallest);
	
	return 0;
}