Programing/백준, 프로그래머스(C++)

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

hye3193 2025. 1. 12. 00:09

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 두 개로 떼웠다

 

최빈값을 구하는 과정을 너무 복잡하게 만든 느낌이라 아쉬움이 남는다

기회가 되면 다시 풀어봐야겠다