https://www.acmicpc.net/problem/2108
[ 문제 ]
수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.
N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.
[ 입력 ]
첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.
[ 출력 ]
첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.
둘째 줄에는 중앙값을 출력한다.
셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.
넷째 줄에는 범위를 출력한다.
[ 입출력 예시 ]
예제 입력 | 예제 출력 |
---|---|
5 1 3 8 -2 2 | 2 2 1 10 |
1 4000 | 4000 4000 4000 0 |
5 -1 -2 -3 -1 -2 | -2 -2 -1 2 |
- 리스트를 하나는 입력된 값들을 다루고(list), 하나는 최빈값(inf)을 다루기 위해 두 개 선언한다.
입력된 값들의 개수를 세어주기 위한 배열(count)를 선언한다. 이때, -4000~4000이므로 배열 인덱스는 음수가 존재하지 않으므로 배열의 길이가 8001까지 되도록 선언한다.
- 몇 개의 수를 받을지에 대한 변수(N)을 선언하여 입력 받아준다.
입력 받으면서 평균을 구하기 위해 입력된 수들의 합을 바로 바로 구해줄 변수(sum)을 선언한다.
sum으로 평균을 구할 것이기 때문에 double형으로 선언하여준다.
- N만큼 루프를 돌려 수를 입력 받고, 그 수를 sum에 더한다. list에 값을 추가하고 그 후 입력된 수에 4000을 더해서 count배열 인덱스 만큼에 넣어준다
(ex. 0 -> count[4000], -4000 -> count[0])
- list는 큰 수와 작은 수의 차이를 비교해줘야하므로 Collections.sort()시켜서 오름차순 정렬시켜준다.
이제 구하고자 하는 값을 하나씩 구해본다.
- 평균을 구하는데, 위에 더해놨던 sum을 N(값의 개수)만큼 나누어준다. Math.round()를 이용하여 첫째 자리에서 반올림한 값을 가져온다.
- mid값은 정렬한 list의 (N/2)번째 값을 가져오면 중간값을 쉽게 가져올 수 있다.
- 최빈값을 알기위해 count변수를 하나씩 돌면서 가장 많이 나온 값을 확인한다. 이때 max변수를 0으로 선언해서 count배열 변수의 값이 max보다 크면 최빈값을 알기 위한 inf리스트를 초기화 후 inf에 해당 인덱스를 저장하고, 만약 max와 같은 값이 나온다면 inf에 또 추가하여준다.
(Set을 선언하여 배열 8001개를 다 돌 필요없이 Set에 저장된 값만 확인해보았는데 시간이 더욱 오래 걸렸다..)
- inf 리스트에는 최빈값이 담겨있는데 이때, inf의 사이즈가 1이라면 inf.get(0)을 통해 최빈값을 반환받고, 최빈값이 여러개 즉, inf의 사이즈가 1보다 크다면 문제에서 2번째 값을 출력하라 하였으므로, inf.get(1)을 통해 두 번째 값을 반환 받아 popular변수에 담아준다.
- 입력 받은 수 중 가장 작은 수와 가장 큰 수의 차이(gap)을 구하는 법은 처음에 sort시킨 list의 0번째 값이랑 list.size()-1 번째 값의 차이를 구해주면 gap이 구해진다.
- 출력문을 한 번 이용해서 한 번에 모든 값들을 출력하여준다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args) throws NumberFormatException, IOException {
// 산술평균 : N개의 수들의 합을 N으로 나눈 값
// 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
// 최빈값 : N개의 수들 중 가장 많이 나타나는 값
// 범위 : N개의 수들 중 최댓값과 최솟값의 차이
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList<Integer> inf = new ArrayList<Integer>();
int[] count = new int[8001];
int N = Integer.parseInt(br.readLine());
double sum = 0;
for(int i=0; i<N; i++) {
list.add(Integer.parseInt(br.readLine()));
sum += list.get(i);
count[list.get(i)+4000]++;
}
Collections.sort(list)
int avg = (int)(Math.round(sum/N));
int mid = list.get(N/2);
int popular = 0;
int max = 0;
for(int i=0; i<count.length; i++) {
if(count[i] > max) {
max = count[i];
inf.clear();
inf.add(i);
}
else if(count[i] == max) {
inf.add(i);
}
else {
continue;
}
}
Collections.sort(inf);
if(inf.size()>1) {
popular = inf.get(1) - 4000;
}
else if(inf.size() == 1 ) {
popular = inf.get(0) - 4000;
}
int gap = list.get(N-1) - list.get(0);
System.out.print(avg + "\n" + mid + "\n" + popular + "\n" + gap);
}
}