[백준알고리즘] 2108번: 통계학 -C++
그렇게 어렵게 풀 문제는 아니다.
실제로 구하라고 하는 값들을 계산하면 된다.
산술평균
산술평균을 구하기 위해서 입력 들어오는 모든 값을 우선 더해주었다. 이 더한 값을 입력이 들어오는 개수인 \(n\)으로 나눠주면 된다.
여기서 입력 값들의 합은 int
의 범위를 넘어서기 때문에 int64_t (double)
로 설정해주어서 오버플로우를 방지했다.
중앙값
중앙값을 구해주기 위해서는 우선 모든 수를 입력받은 뒤에, 각 수가 몇 번 호출되었나 차례대로 확인해본다. \(n\) 개의 수가 입력됐을 때 \(n/2\) 번째 수가 중앙값이 되기 때문에 카운팅 하던 횟수가 \(n/2\) 보다 커지는 경우가 중앙값이 될 것이다. (카운트는 \(1\)부터 시작하며 \(n\)은 홀수이기 때문에 같은 경우는 해당 안됨)
최빈값
최빈값도 마찬가지로 모든 수를 입력 받은 뒤에 각 수가 얼마나 입력됐는가를 확인한다. 여기서는 최빈값이 여러 개일 경우에는 두 번째로 작은 값을 선택하라고 했다.
사실 여기서 두번째로 작은 값이라고 하길래 {가장 작은 값, 두 번째로 작은 값} 이렇게 확인하면 될 줄 알았는데, 첫 번째 예시를 보니 {가장 작은 값, 첫 번째로 작은 값, 두 번째로 작은 값}이었다.
아무튼 그래서 나는 크기가 4인 배열을 정해두고, {카운팅 횟수, 해당 카운팅의 가장 작은 값, 해당 카운팅의 첫 번째로 작은 값, 해당 카운팅의 두 번째로 작은 값}으로 배열을 채워넣었다.
범위
범위의 경우에는 입력을 받을 때 최댓값과 최솟값을 분류해놓았다.
2022.02.28
새롭게 문제를 풀었다. 예전에 푼 코드라고 해서 다시 돌려봤는데 컴파일 에러가 발생한다.
그래서 아래 예전 코드는 놔둔 채로 새로 통과한 코드를 업로드한다.
#include <cstdio>
#include <cmath>
#include <set>
void solve(void);
int main(void) {
solve();
return 0;
}
void solve(void) {
/* 입력 */
unsigned int uiNum = 0;
scanf("%u", &uiNum);
const unsigned int ARR_SIZE = 8001 + 1;
unsigned int arrNum[ARR_SIZE] = { 0, };
for ( unsigned int uiCnt = 0; uiCnt < uiNum; ++uiCnt ) {
int iVal = 0;
scanf("%d", &iVal);
arrNum[iVal + 4000]++;
}
/* 통계학 값 구하기 */
const int VAL_MIN = -4000;
const int VAL_MAX = 4000;
const int VAL_INIT = 4001;
const int MID_IDX = uiNum / 2;
int iSum = 0; //< 합
int iMedian = VAL_INIT; //< 중앙값
int iModeSmaller = VAL_INIT; //< 최빈값2
int iMode = VAL_INIT; //< 최빈값1
int iMin = VAL_MAX; //< 최솟값
int iMax = VAL_MIN; //< 최댓값
int iCnt = 0; //< 카운트
for ( unsigned int uiIdx = 0; uiIdx < ARR_SIZE; ++uiIdx ) {
if ( 0 == arrNum[uiIdx] ) {
continue;
}
const int idx = uiIdx - 4000;
// 합
iSum += (idx * arrNum[uiIdx]);
// 중앙값
if ( MID_IDX < iCnt ) {
// nothing
}
else if ( MID_IDX <= (iCnt = iCnt + arrNum[uiIdx]) ) {
iMedian = idx;
}
// 최빈값
if ( arrNum[iModeSmaller + 4000] < arrNum[uiIdx] ) {
iMode = idx;
iModeSmaller = idx;
}
else if ( arrNum[iModeSmaller + 4000] == arrNum[uiIdx] && iMode == iModeSmaller ) {
iModeSmaller = idx;
}
// 범위
iMin = (iMin < idx) ? iMin : idx;
iMax = (idx < iMax) ? iMax : idx;
}
/* 출력 */
printf("%.0lf\n%d\n%d\n%d",
::round(1.0 * iSum / uiNum) + 0.0,
iMedian,
iModeSmaller,
iMax - iMin);
}
아래는 위의 방법대로 풀이한 방식이다.
#include <iostream>
#include <climits>
#include <cmath>
void solve(void);
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
solve();
}
void solve(void)
{
int n;
std::cin >> n;
int64_t total = 0;
int max_val = INT_MIN;
int min_val = INT_MAX;
int count[8001] = { 0, };
for (int i = 0; i < n; i++)
{
int temp;
std::cin >> temp;
count[temp + 4000]++;
total += temp;
max_val = max_val < temp ? temp : max_val;
min_val = min_val < temp ? min_val : temp;
}
int total_count = 0;
int mid_val = INT_MIN;
int max_count[4]; // count, smallest, second, third
std::fill_n(max_count, 4, INT_MIN);
for (int i = 0; i <= 8001; i++)
{
if (!count[i]) continue;
int curr = i - 4000;
total_count += count[i];
if (n / 2 < total_count && INT_MIN == mid_val)
mid_val = curr;
if (max_count[0] == count[i])
if (INT_MIN == max_count[2])
max_count[2] = curr;
else if (INT_MIN == max_count[3])
max_count[3] = curr;
if (max_count[0] < count[i])
{
max_count[0] = count[i];
max_count[1] = curr;
max_count[2] = INT_MIN;
max_count[3] = INT_MIN;
}
}
std::cout << std::round(total * 1.0 / n) << std::endl;
std::cout << mid_val << std::endl;
std::cout << (INT_MIN == max_count[2] ? max_count[1] : max_count[2]) << std::endl;
std::cout << max_val - min_val;
}
잘못된 점이나 부족한 점 지적해주시면 감사하겠습니다
'algorithm > 백준알고리즘' 카테고리의 다른 글
[백준알고리즘] 1181번: 단어 정렬 -C++ (0) | 2021.01.25 |
---|---|
[백준알고리즘] 11650번: 좌표 정렬하기 -C++ (0) | 2021.01.24 |
[백준알고리즘] 10989번: 수 정렬하기 3 -C++ (0) | 2021.01.24 |
[백준알고리즘] 2751번: 수 정렬하기 2 -C++ (0) | 2021.01.23 |
[백준알고리즘] 1436번: 영화감독 숌 -C++ (0) | 2021.01.23 |