알고리즘/백준

백준 2108 통계학 c++ [컴공과고씨]

시간빌게이츠 2022. 3. 12. 17:16
반응형

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

 

2108번: 통계학

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

www.acmicpc.net

산술 평균은 처음에 float를 썼는데 오류가 나서 double로 바꿔주니 잘 되었다. double 훨씬 더 정확하기 때문에 정확성 문제로 오류를 발생 시키는 것 같았다.

 

중앙값은 그냥 sort해서 (n-1) 후 2로 나눠주면 나왔고 범위도 마찬가지로 sort 후 최대 - 최소 해주면 쉽게 나왔다.

최빈값 같은 경우 처음에 문제를 제대로 읽지 않아 "정수의 절댓값은 4,000을 넘지 않는다" 이 부분을 놓쳐 조금 복잡하게 구현했다. 

처음 구현 방법은 sort한 배열부터 하나하나 검사하면서 중복값이면 count를 하다 다른 값이 나오면 이제까지의 최빈값과 비교하여 지금 카운트한 수가 더 크다면 최빈값을 바꿔주고 아니면 카운트를 1로 다시 바꿔주고 비교하며 진행한다. 여기서 중요한 점은 최빈값이 중복되면 2번째로 작은 수를 출력해야하기 때문에 만약 현재 카운트와 최빈값이 같다면 2번째로 작은 값인지 알기위해 bool형 flag를 사용하여 두 번째면 최빈값을 바꿔주고 아니면 현재 값을 유지하게 구현해주었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
int n;
int num[500001];
int arithmetic_mean(){
    double ans = 0;
    for (int i = 0; i < n;i++){
        ans += num[i];
    }
    return round(ans / n);
}// 산술평균
int medain(){
    return num[(n - 1/ 2];
//중앙값
int mode(){
    int cnt = 0;
    int ans = 0;
    int temp = num[0];
    int result = num[0];
    bool second = false;
    for (int i = 0; i < n;i++){
        if (temp == num[i]){
            cnt++;
        }
        else{
            if(ans < cnt){
                ans = cnt;
                result = num[i - 1];
                second = false;
            }
            else if(ans == cnt && !second){
                result = num[i - 1];
                second = true;
            }
            cnt = 1;
            temp = num[i];
        }
    }
    if(ans < cnt){
        result = num[n - 1];
    }
    else if(ans == cnt && !second){
        result = num[n - 1];
    }
    return result;
}//최빈값
int range(){
    return num[n - 1- num[0];
}//범위
int main(){
    cin >> n;
    for (int i = 0; i < n; i++){
        cin >> num[i];
    }
    sort(num, num + n);
    cout << arithmetic_mean() << '\n';
    cout << medain() << '\n';
    cout << mode2() << '\n';
    cout << range() << '\n';
    return 0;
}
cs

 

"정수의 절댓값은 4,000을 넘지 않는다" 이 문구를 보고 난 후 적용하여 문제를 풀면 더 간단하게 최빈값을 구할 수 있을 것 같아 다시 한번 풀어 보았다. 절대값 4,000을 넘지 않기 때문에 8000짜리 배열을 만들어주고 주어진 정수 0~4000은 4000~8000까지 배열번호 카운트해주고 -4000 ~ -1은 0 ~ 4000 배열 번호에 나올때마다 카운트해서 이 배열안에서 최대값을 구해주면 그 인덱스 번호가 답이 되는데 2번째 작은 값이기 때문에 중복된 값이 있다면 2번째로 나온 최대값의 인덱스를 적어주면 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int mode2(){
    int result;
    int count = 0;
    int cnt2[8001= {0};
    for (int i = 0; i < n;i++){
        cnt2[num[i] + 4000]++;
    }
    int max_mode = *max_element(cnt2, cnt2 + 8001);
    for (int i = 0; i < 8001;i++){
        if(cnt2[i] == max_mode){
            count++;
            result = i - 4000;
        }
        if(count == 2){
            break;
        }
    }
    return result;
}//최빈값
cs

다시 만든 코드.

yea!

반응형