여러가지 스끼리 필요한 문제다.

 

1. 산술평균

math.h에서 제공하는 round함수를 사용하면 가볍게 소수점 첫째자리에서 반올림을 해준다.

다만, 그러기 위해서 나눗셈의 결과를 int형 변수가 아니라 double형 변수에 저장해야 원하는 결과를 얻을 수 있다. 자명하게도 int형 변수는 소수점 아랫자리가 컷트되기 때문.

 

2. 중앙값

왜 \(n\)이 항상 홀수일까 ?

프로그래밍에서 \(n\)이 홀수일 때, \(n / 2\)은 중앙을 가르키기 때문이다.

무슨 말이냐 ?

5개짜리 배열을 만들면, 인덱스가 0, 1, 2, 3, 4가 만들어진다. int형 변수에 \( 5 / 2\)를 저장하면 저장되는 값은 2.

우연히 5개짜리 배열의 중앙 인덱스 값이 나왔다.

 

7개짜리 배열을 만들어보자. 인덱스가 0, 1, 2, 3, 4, 5, 6이 만들어진다. int형 변수에 \( 7 / 2\)를 저장하면 저장되는 값은 3.

이번에도 우연히 7개짜리 배열의 중앙 인덱스 값이 나왔다.

 

사실 우연이 아니라 자명한 것이다. 이와 같은 성질은 알고리즘 문제를 해결할 때 생각보다 자주 쓰이니까 알아두면 좋다 !

따라서, 중앙값은 정렬되어있는 배열의 \(n / 2\)번째 인덱스에 저장되었는 값이 된다.

 

3. 최빈값

나오는 값의 범위가 \([-4000 , 4000]\)이니까, 어떤 수가 몇 번 나왔는지 체크하는 건 어렵지 않다.

다만, 최빈값이 여러 개라면 두번째로 작은 값을 출력해야되는 것이 까다로울 수 있다.

아이디어는 이렇다. 

  1. 사전에 어떤 수의 등장한 횟수들 중 최댓값을 저장한다.
  2. -4000 ~ 4000까지 돌면서 사전에 구한 최댓값과 같은지 확인한다.
  3. 사전에 구한 최댓값과 같은 수를 두 개째 확인하면 그대로 for문을 종료.

4. 범위

중앙값을 위해 이미 배열을 정렬한 상태라고 가정하자.

정렬되어있다면 첫번째 인덱스와 마지막 인덱스가 각각 최솟값, 최댓값임은 자명하다.

마지막 인덱스에 저장된 값에서 첫번째 인덱스에 저장된 값을 빼주자.

 

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int INF = 2147483647;
const int MAX = 10e+8;

ll gcd(ll a, ll b) { for (; b; a %= b, swap(a, b)); return a; }
int num[500001];
int cnt[8001];

int main() {
	ios::ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);

	int n;
	double sum = 0;
	int maxCount = 0;
	cin >> n;

	for (int i = 0; i < n; ++i) {
		cin >> num[i];

		sum += num[i];
		maxCount = max(maxCount, ++cnt[num[i] + 4000]);
	}

	sort(num, num + n);

	// 산술평균
	cout << (int)round(sum / n) << '\n';

	// 중앙값
	cout << num[n / 2] << '\n';
	
	// 최빈값
	int modeValue = -4000, numOfMaxCount = 2;
	for (int i = 0; i < 8001 && numOfMaxCount; ++i) if (cnt[i] == maxCount) {
		modeValue = i - 4000;
		numOfMaxCount--;
	}
	cout << modeValue << '\n';

	// 범위
	cout << num[n - 1] - num[0] << '\n';

	return 0;
}

+ Recent posts