Baekjoon Review

[Silver 3] 2108번 통계학

hanseongbugi 2023. 10. 11. 16:27

https://www.acmicpc.net/problem/2108

 

2108번: 통계학

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

www.acmicpc.net

 

처음 풀었을 때 최빈 값에 대한 알고리즘이 틀렸었다.

왜 그런가 하니 두번째로 작은 값을 잘못 구한 것이였다.

 

최빈 값을 구할 때 만약 나온 횟수가 같으면 두번째로 작은 수를 출력하라고 하였으므로, not_first라는 bool형 플래그값을 줘서 만약 나온 횟수가 같다면 두번째로 작은 값이 저장되도록 한다.

 

또한 문제 풀이 과정 중 모든 테스트 케이스가 맞는데도 틀린 현상이 일어났다.

계속해서 고민과 주변인에게 질문한 결과 float라는 자료형의 문제인 것을 알게 되었다.

평균 값 계산 시 float가 아닌 double을 사용해야한다.

이유는 float과 double의 오차 때문이다. float에 비해 double이 표현할 수 있는 실수의 범위는 더 넓다.

float의 경우 6자리까지 표현할 수 있으며, double의 경우 15자리까지 표현할 수 있다.

이로인해 반올림 연산 시 float을 사용하면, 오차가 생길 수 있어 double을 사용해야한다.

 

예를들어 123456789.123을 float형 변수와 double형 변수에 넣게 된다면,

float의 경우 123456792.000000이 출력되고, double의 경우 123456789.123000이 출력된다.

 

자세한 내용은 아래 글 참고

https://hanseongbugi2study.tistory.com/22

 

<DataType> float와 double의 차이

코딩 테스트 문제를 풀던 중 나누기 연산을 해야하는 문제가 있었다. 나누기 연산 후 소수점 아래 N자리 까지 반올림 연산을 해야하기 때문에 float를 사용하여 문제를 해결하고자 하였다. 하지만

hanseongbugi2study.tistory.com

 

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

int counter[8001] = {0,};

int main(){
    int N;
    cin>>N;
    vector<int> arr;
    arr.assign(N,0);
    double avg = 0;
    for(int i = 0;i<N;i++){
        int input;
        cin>>input;
        arr[i] = input;
        avg += input;
        counter[input+4000] ++;
    }
    avg /= N; // 산술 평균 연산
    sort(arr.begin(),arr.end());
    int mid = arr[N/2]; // 중앙 값 연산

    int min = 0;
    int most = -9999;
    bool not_first = false;
    for(int i = 0;i<8001; i++){
        if(counter[i] == 0) continue;
        if(counter[i] == most){
            if(not_first){
                min = i - 4000;
                not_first = false;
            }
        }
        if(counter[i] > most){
            most = counter[i];
            min = i - 4000;
            not_first = true;
        }
    }
  
    int range = arr[N-1] - arr[0]; // 범위 연산
    double average = round(avg);
    if(avg < 0.5 && avg>-0.5) average = 0;
    cout<<average<<'\n';
    cout<<mid<<'\n';
    cout<<min<<'\n';
    cout<<range<<'\n';
}