본문 바로가기
문제 풀이/백준(BOJ)

[C] 백준 2108번 : 통계학

by 희조당 2021. 5. 11.
728x90

www.acmicpc.net/problem/2108

 

2108번: 통계학

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

www.acmicpc.net


데이터 추가로 잘못된  풀이가 되었습니다 ㅠ.ㅠ

https://codinghejow.tistory.com/176 여기에 좋은 풀이가 있습니다!

문제 접근

 산술평균 : 값을 입력받을 때 변수 sum에 입력받은 값들을 다 더한 뒤, n만큼 나눠 출력한다. 이 때 소수점 첫째자리 반올림이니 0.f로 출력한다.

 중간값 : 입력받는 값의 개수는 항상 홀수이므로, 정렬한 배열의 중간값을 출력한다. 이 때, 배열의 인덱스는 0부터 시작하니 (n + 1) / 2 - 1이 중간값의 인덱스이다.

 최빈값 : 반복문을 통해서 최대 빈도를 찾는다. 이후 최대 빈도와 맞는 값을 배열에 저장한다. 최대 빈도와 맞는 값이 여러 개라면 변수 flag를 통해서 최대 빈도인 값이 여러 개임을 알린다. 변수 flag가 1이라면 배열의 첫째 값(0번 인덱스)를 출력, 아니라면 배열의 두번째 값(1번 인덱스)를 출력한다.

 범위 : 값을 입력받을 때 최솟값, 최댓값을 찾는다. 이후 최댓값-최솟값을 출력한다.

느낀점

처음에 최빈값 때문에 생각보다 애를 먹었다. 하지만 차근차근 접근하다보니 풀 수 있었다. 처음 제출할 때는 퀵 정렬이 아닌 쉘 정렬을 사용했다가 시간 초과가 발생해서 그냥 퀵 정렬로 실행했다.

코드

#include <stdio.h>
#include <stdlib.h>
#define size1 500001
#define size2 8001

int compare(const void* a, const void* b) {
	if (*(int*)a > *(int*)b) return 1;
	else if (*(int*)a < *(int*)b) return -1;
	else return 0;
}

int arr[size1] = { 0, };
int cnt[size2] = { 0, }; // 빈도 배열

int main() {
	int n;
	int sum = 0;
	int min = 4001, max = -4001;
	int mode = 0, flag = 0, max_cnt = 0, idx = 0;
	int mode_arr[4001] = { 0, }; // 최반값 배열
	scanf("%d", &n);
	for (int i = 0; i < n;i++) {
		scanf("%d", &arr[i]);

		sum += arr[i];

		if (arr[i] < min) min = arr[i];
		if (arr[i] > max) max = arr[i];

		cnt[arr[i]+4000]++;
	}
	qsort(arr, n,sizeof(int),compare);

	for (int i = 0; i < size2;i++) { // 최고 빈도 찾기
		if (cnt[i] > max_cnt) max_cnt = cnt[i];
	}
	for (int i = 0; i < size2; i++) { // 최고 빈도와 맞는 값을 mode_arr에 저장
		if (cnt[i] == max_cnt) {
			flag++;
			mode_arr[idx++] = i - 4000;
		}
	}

	if (flag == 1) {
		mode = mode_arr[0];
	}
	else mode = mode_arr[1];

	printf("%0.f\n", (double)sum / n);
	printf("%d\n", arr[(n + 1) / 2 - 1]);
	printf("%d\n", mode);
	printf("%d", max - min);

	return 0;
}

댓글