BOJ 2108 - 통계학
https://www.acmicpc.net/problem/2108
2108번: 통계학
첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.
www.acmicpc.net
이번 문제는 수의 범위가 4000을 넘지 않기 때문에 자바 API에서 제공하는 정렬 알고리즘으로도 풀 수 있는 문제이다.
하지만 보다 빠른 결과를 위해 counting sort를 적용해 보겠다.
findAvg()
첫째로 산술평균값을 구하는 메서드 findAvg() 를 보면, 문제에 소수점 이하 첫째 자리에서 반올림한 값을 출력해야한다고 명시되어있다.
따라서 자바 API 에서 제공하는 소수 첫째 자리 반올림해 주는 Math.round() 메서드를 이용해 해결한다.
findMedian()
중앙값을 구하는 findMedian() 메서드는 이해하기 더더욱 쉽다. counting sort 배열과 전체 N 개수를 2로 나눈 중간값을 받아와 counting sort 배열 값이 0 이상일 때 count를 증가시키고, count값이 중간값과 같아질 때 결과값을 반환하면 된다.
findMod()
최빈값을 구할 때는 먼저 N개의 수 중 중복되는 최대 개수 maxNumber를 구해준다.
문제에 최빈값이 여러 개 있을 경우 최빈값 중 두 번째로 작은 값을 출력해야 한다고 명시하고 있으니, counting sort 배열을 이용하여 오름차순으로 2번째 값을 출력시켜주면 된다.
findRange()
counting sort 배열을 이용해 최대값과 최소값을 구하고, 그 결과값이 음수가 나올 수 있으므로 Math.abs() 메서드를 이용해 절대값을 구해 반환시켜준다.
굳이 4개의 메서드로 만들지 않고 하나로 합치는 것이 리소스가 더 적게 들지만, 문제를 좀 더 직관적이게 풀고 싶어서 4개의 메서드로 나누어 풀이하였다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int number = Integer.parseInt(br.readLine());
int[] arr = new int[number];
for (int i = 0; i < number; i++) {
arr[i] = Integer.parseInt(br.readLine());
}
int[] countingSort = new int[8001];
for (int i = 0; i < arr.length; i++) {
countingSort[arr[i] + 4000]++;
}
int[] countingSortCopy = Arrays.copyOf(countingSort, countingSort.length);
int[] countingSortCopy2 = Arrays.copyOf(countingSort, countingSort.length);
sb.append(findAvg(arr) + "\n" + findMedian(arr.length/2, countingSort) + "\n" + findMod(arr, countingSortCopy) + "\n" + findRange(countingSortCopy2));
System.out.println(sb);
br.close();
}
public static int findAvg(int[] arr) {
double sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return (int)Math.round(sum / arr.length);
}
public static int findMedian(int number, int[] countingSort) {
int result = 0;
int count = 0;
for (int i = 0; i < countingSort.length; i++) {
while (countingSort[i] > 0) {
countingSort[i]--;
count++;
if (count == number + 1) {
return result = i - 4000;
}
}
}
return result;
}
public static int findMod(int[] arr, int[] countingSort) {
int result = 0;
int maxNumber = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
maxNumber = Math.max(countingSort[arr[i] + 4000], maxNumber);
}
int count = 0;
for (int i = 0; i < countingSort.length; i++) {
if (countingSort[i] == maxNumber) {
count++;
result = i - 4000;
if (count == 2) {
break;
}
}
}
return result;
}
public static int findRange(int[] countingSort) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < countingSort.length; i++) {
if (countingSort[i] > 0) {
min = i - 4000;
break;
}
}
for (int i = countingSort.length - 1; i >= 0; i--) {
if (countingSort[i] > 0) {
max = i - 4000;
break;
}
}
return Math.abs(max - min);
}
}