ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ 2108 ] 통계학
    알고리즘/BOJ 2021. 8. 12. 18:32

    < 정렬 > - < 실버 4 >

     

    [ 2108 ]

    통계학

    수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.

    1. 산술평균 : N개의 수들의 합을 N으로 나눈 값
    2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
    3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값
    4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이

    N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.

     

    :: 입력

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

    :: 출력

    첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.

    둘째 줄에는 중앙값을 출력한다.

    셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.

    넷째 줄에는 범위를 출력한다.


     

    - try 1 

    : 숫자를 벡터에도 저장하고 배열에도 저장해서 각자 필요한 곳에 사용하려고 했는데 

    연산이 복잡해져서 그런가 틀림

     

    - try 2

    : 해답코드를 보고 숫자를 저장할 배열과 숫자가 나온 횟수를 저장할 배열

    두 배열을 이용해서 풀었음

    자잘한 부분을 많이 틀려서 여러번 수정함

     

    더보기

    1. 마지막 반복문에서 조건에 i = indx; i < 8001; i++ 이 아니라 i = indx+1
    2. 마지막 반복문에서 break 을 넣지 않아서 최빈값 중 가장 큰 값이 출력됨

    3. cmath.h 에 있는 round 함수를 몰랐음

    ** round = 인자로 들어온 값을 반올림해서 반환하는 함수

    4. 홀수개의 수 중에서 가운데 값을 구할 때 (n-1)/2가 아니라 (n/2)+1 이라고 생각함

     

      정답  코드  

    #include <iostream>
    #include <string>
    #include <queue>
    #include <algorithm>
    #include<cmath>
    
    using namespace std;
    #define endl "\n"
    
    int cnt[8001] = { 0, };
    int nums[500001] = { 0, };
    
    int main() {
    	ios_base::sync_with_stdio(0);
    	cin.tie(0);
    
    	int n;
    	cin >> n;
    
    	int total = 0;
    
    	for (int i = 0; i < n; i++) {
    		cin >> nums[i];
    		total += nums[i];
    		cnt[nums[i] + 4000]++;
    	}
    
    	sort(nums, nums + n);
    
    	int indx;
    	int max_cnt = 0;
    
    	for (int i = 0; i < 8001; i++) {
    		if (cnt[i] > max_cnt) {
    			indx = i;
    			max_cnt = cnt[i];
    		}
    	} // 이때 max_cnt에는 가장 많이 나온 숫자의 횟수가 저장
    	// indx 는 해당수에 4000을 더한값이 됨
    	// 해당 indx 에 저장된 값은 같은 빈도를 가진 수 중에 가장 작은 수가 되기 때문에
    	// indx부터 탐색을 시작하면 그 이후에 같은 빈도를 가진 수는 두번째로 작은 수가 됨
    
    	for (int i = indx+1; i < 8001; i++) {
    		if (cnt[i] == max_cnt) {
    			indx = i;
    			break;
    		}
    	}
    
    	int avg = round((double)total / n); // 평균
    	int mid = nums[(n-1)/2]; //중간값
    	int many = indx - 4000; //최빈값
    	int range = nums[n-1] - nums[0]; // 범위
    
    	cout << avg << endl;
    	cout << mid << endl;
    	cout << many << endl;
    	cout << range << endl;
    
    	return 0;
    }
준생e