수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.
N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.
첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.
3
0
0
-1
1
4000
5
-1
-2
-3
-1
-2
첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.
둘째 줄에는 중앙값을 출력한다.
셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.
넷째 줄에는 범위를 출력한다.
0
0
0
1
(0 + 0 + (-1)) / 3 = -0.333333... 이고 이를 첫째 자리에서 반올림하면 0이다. -0으로 출력하면 안된다.
4000
4000
4000
0
-2
-2
-1
2
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
int[] arr2 = new int[8001]; // 정수의 절댓값은 4000이 넘지 않기 때문에
int sum = 0; int second = 0; // 두 번쨰로 작은 값 저장 변수
int count = 0; int max = 0;
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
sum += arr[i];
}
Arrays.sort(arr);
// 최빈값 구하기
for (int i = 0; i < n; i++) {
arr2[arr[i] + 4000]++;
max = Math.max(max, arr2[arr[i] + 4000]);
}
for (int i = 0; i < arr2.length; i++) {
if (arr2[i] == max) {
count++;
second = i - 4000;
}
if (count == 2) { // 최빈값이 두 개 이상
second = i - 4000;
break;
}
}
System.out.println((int)Math.round((double) sum / (double) n)); // 합
System.out.println(arr[(arr.length/2)]); // 중앙값
System.out.println(second);
System.out.println(arr[n-1]-arr[0]); // 범위
}
}
→ Arrays.sort() 사용
다른 건 쉽게 풀었는데 최빈값이 문제였음.. 여러 개면 2번째로 작은 수를 출력해야해서 시간이 좀 걸렸다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int[] arr = new int[8001]; // 입력값의 범위 : -4000 ~ 4000
int sum = 0;
int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE;
// median 과 mode 는 -4000~4000 을 제외한 수로 초기화
int median = 10000; // median = 중앙값
int mode = 10000; // mode = 최빈값
for(int i = 0; i < N; i++) {
int value = in.nextInt();
sum += value;
arr[value + 4000]++;
if(max < value) max = value;
if(min > value) min = value;
}
// 순회
int count = 0; // 중앙값 빈도 누적 수
int mode_max = 0; // 최빈값의 최댓값
boolean flag = false; // 이전의 동일한 최빈값이 1번만 등장했을 경우 true, 아니면 false
for(int i = min + 4000; i <= max + 4000; i++) {
if(arr[i] > 0) {
// 중앙값 : 누적횟수가 전체 전체 길이의 절반에 못 미친다면
if(count < (N + 1) / 2) {
count += arr[i]; // i 값의 빈도수를 count 에 누적
median = i - 4000;
}
// 최빈값 : 이전 최빈값보다 현재 값의 빈도수가 더 높을 경우
if(mode_max < arr[i]) {
mode_max = arr[i];
mode = i - 4000;
flag = true; // 처음이므로 true 로 변경
}
// 이전 최빈값 최댓값과 동일한 경우면서 한 번만 중복되는 경우
else if(mode_max == arr[i] && flag == true) {
mode = i - 4000;
flag = false;
}
}
}
System.out.println((int)Math.round((double)sum / N)); // 산술평균
System.out.println(median); // 중앙값
System.out.println(mode); // 최빈값
System.out.println(max - min); // 범위
}
}
→ 카운팅정렬 사용
아직 구조를 제대로 이해 못함