백준 2108번) 통계학
본문의 코드보다 더 효율적인 코드가 분명 존재합니다.
참고만 해주시면 감사하겠습니다.
코드 지적은 언제나 환영입니다.
풀이
입력받은 숫자를 통해 산술평균, 중앙값, 최빈값, 범위를 출력하는 문제이다.
산술평균은 일반적인 평균처럼 합을 원소의 갯수로 나누면 된다.
중앙값은 우선 sort를 통하여 배열을 오름차순으로 정렬해준다.(sort는 기본적으로 오름차순 정렬이다.)
문제에서 N은 홀수라고 언급하였기 때문에 중앙 값은 tc/2를 통해 인덱스를 접근하면 된다.
개인적으로 최빈값이 가장 어려웠다.
메모리 낭비 때문에 아래의 코드처럼 배열 크기를 크게 만들기 싫었다. 하지만 묘수가 떠오르지 않아 배열의 크기를 8001로 정적할당하여 풀었다.
N의 범위는 -4000 ~ 4000 이기 때문에 0을 포함한 8001자리가 필요하기 때문에 list2[8001]을 선언하였다.
쓰레기 값을 정리하기위해 0으로 초기화 시켰고 list를 for문을 통해 탐색하면서 해당 값을 list2의 인덱스로 이용하여 해당 인덱스의 값을 증가시켰다.
max_element는 vector에서 가장 큰 원소를 찾을 수 있는 함수이다.
max_element를 통해 빈도수가 가장 큰 수를 가져오고 다시 for문을 통해 list2에서 가장 큰 빈도수와 동일한 원소의 인덱스를 list3에 저장한다.
만약 list3의 크기가 1이라면 최빈값이 1개라는 의미이고
크기가 1이 아니라면 최빈값이 2개 이상 이라는 의미이다.
따라서 list3의 크기가 1이 아닐 때 list3를 오름차순으로 정렬하고 배열의 1번 인덱스 값을 가져오면 최빈값 중 두 번째로 작은 값을 가져올 수 있다.
범위는 크기가 1일 때는 0이고 1이 아닐 때는 가장 큰 값에서 가장 작은 값을 빼주면 된다.
코드
#include "iostream"
#include "vector"
#include "algorithm"
#include "cmath"
using namespace std;
void print_average(int *sum, int *tc);
void print_mid(vector<int> *list, int *tc);
void print_frequency(vector<int> *list, int *tc);
void print_range(vector<int> *list);
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int tc, sum = 0;
cin >> tc;
vector<int> list;
for(int i = 0 ; i < tc ; i++){
int tmp;
cin >> tmp;
sum += tmp;
list.push_back(tmp);
}
sort(list.begin(), list.end());
print_average(&sum, &tc);
print_mid(&list, &tc);
print_frequency(&list, &tc);
print_range(&list);
return 0;
}
void print_average(int *sum, int *tc){
double average;
average = (double)(*sum)/(*tc);
if(-1 < average && average < 0) average = 0;
cout << round(average) << '\n';
}
void print_mid(vector<int> *list, int *tc){
cout << (*list)[*tc/2] << '\n';
}
void print_frequency(vector<int> *list, int *tc){
//최빈값 출력
int list2[8001] = {0, };
for(int i = 0 ; i < *tc ; i++){
list2[(*list)[i]+4000]++;
}
int max_frequency = *(max_element(list2, list2+8001));
vector<int> list3;
for(int i = 0 ; i < 8001 ; i++){
if(list2[i] == max_frequency){
list3.push_back(i-4000);
}
}
if(list3.size() == 1){
cout << list3[0] << '\n';
}else{
sort(list3.begin(), list3.end());
cout << list3[1] << '\n';
}
}
void print_range(vector<int> *list){
if((*list).size() > 1){
cout << (*list)[(*list).size()-1] - (*list)[0] << '\n';
}else{
cout << 0;
}
}