[C++][백준 2108] 통계학
https://www.acmicpc.net/problem/2108
제출 코드
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
bool comp(pair<int, int>& a, pair<int, int>& b)
{
if (a.second == b.second)
return a.first < b.first;
return a.second > b.second;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
vector<int> v;
int n, input, sum = 0;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> input;
sum += input;
v.push_back(input);
}
sort(v.begin(), v.end());
vector<pair<int, int>> m;
m.push_back(make_pair(v[0], 1));
for (int i = 1; i < n; i++)
{
if (v[i] == v[i - 1])
m.back().second++;
else
m.push_back(make_pair(v[i], 1));
}
sort(m.begin(), m.end(), comp);
cout << floor(float(sum) / n + 0.5) << '\n';
cout << v[n / 2] << '\n';
if (m[0].second == m[1].second)
cout << m[1].first << '\n';
else
cout << m[0].first << '\n';
cout << (v.back() - v.front()) << '\n';
}
문제에서는 총 4가지 값을 구해야 하고, 아래는 각각 값을 어떤 방식으로 구했는지에 대한 설명이다
1. 산술평균(소숫점 아래 첫째 자리에서 반올림)
: 우선 정수들을 입력받을 때 sum 변수에 해당 정수들을 다 더해주었다
그리고 마지막에 n으로 나눈 값을 반올림하여 출력하였다
(-0이 출력되지 않게 하기 위해 0.5를 더하고 내림함수를 사용하는 방식으로 반올림을 구현했는데, 그냥 double형을 사용하고 0.0을 더해주면 round 함수를 사용해도 -0이 출력되지 않는다고 한다)
2. 중앙값
: vector v에 순서대로 정수들을 push하고 sort 해주었기 때문에 n/2번 인덱스(n은 늘 홀수이므로)의 값이 중앙값이 된다
3. 최빈값
: 최빈값을 구하기 위해 새로운 vector인 m을 만들어주었다(first: 값, second: 빈도수)
만약 자신의 앞 요소와 다른 값이면 새로운 pair을 추가해주고,
앞 요소와 같은 값이면 해당값(가장 최근에 추가된 pair = m.back())의 second에 1씩 더해준다
v vector가 이미 오름차순으로 정렬되어있는 상태이기 때문에 해당 방법으로 find나 binary_search와 같은 함수 없이도 총 몇 번 등장했는지 파악할 수 있었다
위와 같은 방법으로 숫자를 세 주고, 다시 최빈값을 기준으로 정렬해주었다
이 때, 최빈값이 여러 개라면 두번째로 작은 수를 출력해야 하기 때문에 comp 함수에서 빈도수가 같다면 오름차순으로 정렬하도록 코드를 작성하였다
만약 m[0]의 빈도수와 m[1]의 빈도수가 같다면 최빈값이 두 개 이상이란 의미이므로 두번째로 작은 수인 m[1]을 출력하고, 빈도수가 다르다면 최빈값은 m[0] 하나이므로 이를 출력하였다
4. 범위
v vector는 오름차순으로 정렬되어 있기 때문에 가장 뒤쪽에 위치한 값(v.back())에서 가장 앞에 위치한 값(v.front())를 빼 주면 범위가 나온다
개수를 세는 게 필요하면 map을 사용하는 게 나을까 생각도 해봤으나 어차피 중앙값을 구하려면 또 for문을 돌아야 할 것이기 때문에 그냥 vector 두 개로 떼웠다
최빈값을 구하는 과정을 너무 복잡하게 만든 느낌이라 아쉬움이 남는다
기회가 되면 다시 풀어봐야겠다