본문 바로가기

프로그래밍/PS

[C++] 백준 2108번: 통계학

반응형

2108번: 통계학

 

 

2108번: 통계학

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

www.acmicpc.net

이번 문제는 네 가지의 출력을 해야한다.

그래서 각 출력을 작은 목표로 차근차근 풀어 나가면 다가가기 쉬울 것이다.

 

1. 산술평균

평균은 각 수를 입력받을 때, 입력받은 수를 합한 뒤 N으로 나눠 출력하면 된다.

이 때, 소숫점 아래 첫 번째 자리에서 반올림을 해야하므로 round 함수를 이용하고 int로 캐스팅하여 출력했다.

각 예제에 대한 출력도 옳게 나온다.

#include <cstdio>
#include <algorithm>

using namespace std;

int main() {
	int N;
	scanf("%d", &N);
	int* nums = new int[N];
	double average = 0;
	for (int i = 0; i < N; i++) {
		scanf("%d", nums + i);
		average += nums[i];
	}
	printf("%d\n", (int)round(average / N));
	delete[] nums;
	return 0;
}

 

2. 중앙값

중앙값은 입력받은 수들을 정렬한 뒤, 가운데 인덱스(N/2)를 출력하면 된다.

N이 홀수 이므로 N/2가 가운데 인덱스가 된다는 것은 명백하다.

각 예제에 대한 출력도 옳게 나온다.

#include <cstdio>
#include <algorithm>

using namespace std;

int main() {
	int N;
	scanf("%d", &N);
	int* nums = new int[N];
	for (int i = 0; i < N; i++) {
		scanf("%d", nums + i);
	}
	sort(nums, nums + N);
	printf("%d\n", nums[N / 2]);
	delete[] nums;
	return 0;
}

 

3. 최빈값

이 때에는 숫자그 숫자에 대한 빈도를 한 번에 담은 뒤 정렬하면 될 것이다.

그래서 1966번: 프린터 큐에서와 같이 pair를 활용하기로 했다.

vector에 pair<int, int>를 담고 첫 번째에는 숫자를, 두 번째에는 빈도를 담았다.

vector를 초기화 할 때는 -4000 ~ 4000의 범위 내 모든 정수 8001개에 대해 빈도 0으로 push했다.

수를 입력 받으면서 해당하는 수의 빈도를 1씩 증가시켰다.

정렬할 때는 빈도 기준으로 내림차순 정렬하되, 같은 빈도 내에서는 숫자 기준으로 오름차순 정렬을 해야 하므로 임의로 정의한 compare 함수를 이용했다.

각 예제에 대한 출력도 다행히 옳게 나온다.

#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

bool compare(const pair<int, int>& lhs, const pair<int, int>& rhs) {
	if (lhs.second == rhs.second)
		return lhs.first < rhs.first;
	return lhs.second > rhs.second;
}

int main() {
	int N;
	scanf("%d", &N);
	int* nums = new int[N];
	vector<pair<int, int>> frequency;
	for (int i = 0; i < 8001; i++) {
		frequency.push_back(make_pair(i - 4000, 0));
	}
	for (int i = 0; i < N; i++) {
		scanf("%d", nums + i);
		frequency[nums[i] + 4000].second++;
	}
	sort(frequency.begin(), frequency.end(), compare);
	printf("%d\n", frequency[0].second == frequency[1].second ?
		frequency[1].first : frequency[0].first);
	delete[] nums;
	return 0;
}

 

4. 범위

중앙값을 구할 때 정렬했던 배열의 0번 요소와 N - 1번 요소의 차를 출력하면 된다.

어렵지 않게 예제에 대해 옳게 출력한다.

#include <cstdio>
#include <algorithm>

using namespace std;

int main() {
	int N;
	scanf("%d", &N);
	int* nums = new int[N];
	for (int i = 0; i < N; i++) {
		scanf("%d", nums + i);
	}
	sort(nums, nums + N);
	printf("%d\n", nums[N - 1] - nums[0]);
	delete[] nums;
	return 0;
}

 

 

이제 위의 네 코드를 합쳐야 한다. 누락, 중복 없이 잘 합치면 아래와 같은 코드가 완성된다.

#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

bool compare(const pair<int, int>& lhs, const pair<int, int>& rhs) {
	if (lhs.second == rhs.second)
		return lhs.first < rhs.first;
	return lhs.second > rhs.second;
}

int main() {
	int N;
	scanf("%d", &N);

	vector<pair<int, int>> frequency;
	for (int i = 0; i < 8001; i++) {
		frequency.push_back(make_pair(i - 4000, 0));
	}

	int* nums = new int[N];
	double average = 0;
	for (int i = 0; i < N; i++) {
		scanf("%d", nums + i);
		average += nums[i];
		frequency[nums[i] + 4000].second++;
	}

	sort(nums, nums + N);
	sort(frequency.begin(), frequency.end(), compare);

	printf("%d\n", (int)round(average / N));
	printf("%d\n", nums[N / 2]);
	printf("%d\n", frequency[0].second == frequency[1].second ?
		frequency[1].first : frequency[0].first);
	printf("%d\n", nums[N - 1] - nums[0]);

	delete[] nums;
	return 0;
}

다행히 예제에 대한 출력도 잘 나온다.

혹시 몰라, WSL에서 백준 채점 환경과 동일한 g++ 8.3.0에서 컴파일을 시도하자 아래와 같은 오류가 발생한다.

test.cc: In function ‘int main()’:
test.cc:33:32: error: ‘round’ was not declared in this scope
            printf("%d\n", (int)round(average / N));
                                                   ^~~~~
test.cc:33:32: note: suggested alternative: ‘rand’
             printf("%d\n", (int)round(average / N));
                                                    ^~~~~ rand

VS에서는 정상적으로 컴파일이 됐지만, 사실 round는 cmath를 include해야 사용할 수 있다.

이를 바로잡으니 정상 컴파일 됐다. 다음에는 제대로 확인해야겠다.

이번 문제를 풀면서 여러 과제가 주어졌을 때 한 번에 풀려고 하는 것보다 작은 목표로 나눈 뒤 차근차근 해결하면 금방 해결할 수 있음을 깨달았다.

반응형