[C++] 백준 2108. 통계학

멋진감자·2024년 12월 15일
1

알고리즘

목록 보기
44/65
post-thumbnail

문제

입출력

풀이

이 문제를 풀 때 두 가지가 좀 껄쩍지근했는데

먼저 산술평균을 구할 때 반올림.
cmathround 함수를 사용해서 해결했다.

두 번째는 최빈값.
중복값도 받으면서 정렬이 되어야 하기에 조금 까다롭게 느껴졌다.
음의 정수가 있어서 인덱스 기반으로 풀기도 좀 지저분할 것 같았다.

일단 vector에 n개를 입력받는 동시에 sum, max, min 값을 계산한다.
입력이 끝나면 vector 오름차순 정렬으로 산술평균, 범위, 중앙값까지 해결완

남은 것은 최빈값인데
최빈값이 여러 개일 경우 두 번째로 작은 값을 출력하라고 했기 때문에
먼저 각 값의 빈도수를 저장할 map
최빈값 후보를 담아둘 vector를 하나 더 만들었다.

정렬된 vector를 돌며 map[값]++을 해주고
다시 map을 돌며 두 번째 vector에 최빈값들을 업데이트하면 된다.
vector의 size가 1이면 그 값을, 아니면 vector[1]이 출력할 최빈값이다.

급 map 순회 복습

1. iterator 로 순회

#include <map>
using namespace std;

map<int, int> m;
...

for (auto it = m.begin(); it != m.end(); it++) {
	cout << it->first << " " << it->second;
}

2. 범위 기반 순회

#include <map>
using namespace std;

map<int, int> m;
...

for (auto pair : m) {
	cout << pair.first << " " << pair.second;
}

코드

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	int n;
	cin >> n;

	if (n == 1) {
		int num;
		cin >> num;
		cout << num << "\n" << num << "\n" << num << "\n" << "0";
		return 0;
	}

	vector<int> v(n);

	int sum = 0;
	int maxi = -4001;
	int mini = 4001;
	for (int i = 0; i < n; i++) {
		cin >> v[i];
		sum += v[i];
		maxi = max(maxi, v[i]);
		mini = min(mini, v[i]);
	}
	sort(v.begin(), v.end());

	map<int, int> m;
	for (int i = 0; i < n; i++) {
		m[v[i]]++;
	}

	int cnt = 1;
	vector<int> v2;
	for (auto pair : m) {
		if (pair.second == cnt) {
			v2.push_back(pair.first);
		}
		else if (pair.second > cnt) {
			v2.clear();
			v2.push_back(pair.first);
			cnt = pair.second;
		}
	}

	int avg = round(1.0 * sum / n);
	int mid = v[n / 2];
	int mode = v2.size() == 1 ? v2[0] : v2[1];
	int range = maxi - mini;

	cout << avg << "\n" << mid << "\n" << mode << "\n" << range;

	return 0;
}

채점

profile
난멋져

0개의 댓글