본문 바로가기
C++/백준

[C++백준] 실버 4/ 2108번 통계학

by Meaning_ 2022. 2. 2.
728x90
반응형

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

 

2108번: 통계학

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

www.acmicpc.net

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
#include <iostream>
#include<map>
#include<algorithm>
#include<vector>
#include<cmath>
 
using namespace std;
 
 
int main() {
    
    vector<int>v;
    int arr[8001= {0,};
    
    int n;
    double total=0;
    scanf("%d"&n);
    
    for (int i = 0; i < n; i++) {
        int num;
        scanf("%d"&num);
        total += num;
        v.push_back(num);
        arr[num + 4000]++;
    
    }
 
    int flag = 0;
    int max = 0;
    sort(v.begin(),v.end());
 
    for (int i = 0; i < 8001; i++) {
        if (arr[i] > max) {
            max = arr[i];
            flag = i; //최빈값 중 첫번째 값
        }
    }
    
    for (int i = flag + 1; i < 8001; i++) {
        if (arr[i] == max) {
            flag = i;
            break;
        }
    }
 
    int mean = round(total / n);
    printf("%d\n", mean);
    int mid = n/2;
    printf("%d\n", v[mid]);
    printf("%d\n", flag-4000);
    printf("%d\n", v[n - 1- v[0]);
 
    
    
 
    return 0;
}
 
cs

 

이 문제는 vector로 풀다가 계속 시간초과나서 결국 다른 사람의 코드를 봤다.

결국 문제가 까탈스러운것은 최빈값 때문이였는데 arr[원소]=원소가 중복된 개수 이런식으로 설정해줘야 한다.

예를 들어 -8이 1번 나왔다면 arr[-8]=1이 되는데 음수인덱스는 불가능하다.

이때 문제의 조건이 입력되는 정수가 -4000부터 4000까지 라는 것이다. 그렇다면 인덱스는 총 8001개로 한정지을 수 있다!

그래서 arr[8001]이라고 초기화를 해주고 입력받을때 arr[num+4000]을 해주면 나중에 인덱스-4000을 하면 되니까 음수인덱스를 자유자재로 컨트롤 할 수 있다. 

 

 if (arr[i] > max) {
            max = arr[i];
            flag = i; --> 최빈값 중 첫번째로 나온 값을 flag에 저장해놓고

 

        }
for (int i = flag + 1; i < 8001; i++) {

--> flag+1을 통해 첫번째 최빈값를 제외시켜서 두번째 최빈값을 찾는다.

        if (arr[i] == max) {
            flag = i;
            break; --> 두번째 최빈값만 찾으면 되니까 찾고 나서는 반복문을 빠져나온다.
        }
    }

 

처음썼던 코드 + 틀린 이유 생각

 

처음에는 vector를 통해 v<중복되는 개수, 원소> 이런식으로 저장해주었다.

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
int count = 0;
 
vector<pair<intint>> v;
 
int count = 0;
 
vector<pair<intint>> v;
for (int i = 0; i < n; i++) {
        int current = 0;
        for (int j = i; j < n; j++) {
            if (arr[i] == arr[j]) {
                current++;
            }
            if (current >= count) {
                count = current;
            }
        }
        v.push_back(pair<intint>(count, arr[i]));//개수 원소
}
    
vector<int>mode;
for (int i = 0; i < v.size(); i++) {
        if (v[i].first == count) {
            mode.push_back(v[i].second);
        }
}
//중복제거(이미 정렬은 arr부터 정렬해놔서 상관 x)
unique(mode.begin(), mode.end());
if (mode.size() == 1) {
        cout << mode.front() << endl;
    }
else {
        mode.erase(mode.begin() + 0);
        cout << mode.front() << endl;
    }
cs

 

 

아무래도 8번째 줄 부터 19번째 줄까지 이중 for문을 써서 시간이 확 늘어난 것 같다. 아무래도 8001개를 탐색하다보니..

확실히 arr[원소]=중복개수 --> 이런식으로 바로 한번만 탐색해주는게 시간을 훨씬 줄일 수 있었던 것 같다.

 

728x90
반응형

댓글