smooth waters run deep

1d-1c/BOJ

2108_통계학 (JAVA)

yeon_11 2020. 11. 4. 11:36
 

2108번: 통계학

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

www.acmicpc.net

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

		int N = Integer.parseInt(br.readLine());

		int max = 0; int min = 4000;
		int sum = 0;
		int[] input = new int[N];
		for(int i=0; i<N; i++){
			input[i] = Integer.parseInt(br.readLine());
			max = Math.max(max, input[i]); //input[]의 최대값
			min = Math.min(min, input[i]);
			sum += input[i];
		}

		int[] counting = new int[max+1]; //카운팅(횟수)
		int[] result = new int[N]; //정렬 후

		if(min<0){ //음수 포함 -> 모든 원소 0이상으로 만들기
			for(int i=0; i<N; i++){
				input[i] += Math.abs(min);
			}
			counting = new int[max+Math.abs(min)+1];
		}
		else min = 0;


		max = 0; //counting[]의 최대값
		for(int i=0; i<N; i++){
			counting[input[i]]++;
			max = Math.max(max, counting[input[i]]);
		}

		List<Integer> temp = new ArrayList<>(); //최빈값 구하는 리스트
		for(int i=0; i<counting.length; i++){
			if(counting[i] == max)
				temp.add(i-Math.abs(min));
		}
		Collections.sort(temp);
		if(temp.size()==1)
			max = temp.get(0); //최빈값을 의미
		else
			max = temp.get(1);



		for(int i=1; i<counting.length; i++){
			counting[i] += counting[i-1]; //누적합 계산
		}

		for(int i= input.length-1; i>=0; i--){
			result[--counting[input[i]]] = input[i]-Math.abs(min); //정렬 끝
		}


		bw.write(Integer.toString((int)Math.round((double)sum/N))+'\n'); //산술평균
		bw.write(Integer.toString(result[N/2])+'\n'); //중앙값
		bw.write(Integer.toString(max)+'\n'); //최빈값
		bw.write(Integer.toString(Math.abs(result[N-1]-result[0]))+'\n'); //범위

		br.close(); bw.close();
	}


}

 

카운팅 정렬을 이용하면 출력 네 가지를 한 번에 해결할 수 있다.

 

카운팅 정렬 (Counting Sort)

Counting Sort - 원소 간 비교 과정을 거치지 않고 정렬하는 방법 - 시간복잡도 = O(n) - O(nlogn)의 Quick Sort(퀵 정렬)보다 빠르지만, 사용할 수 있는 경우가 제한적이다. : 배열을 이용해 정렬을 수행하기

yeone2ee.tistory.com

 

입력에 음수가 포함되어 있으므로,

input[] 원소 중 최소값 == 음수로 판단할 수 있다.

input[i]+Math.abs(min) 을 하여 모든 원소가 0이상이 되도록 만들어준다.

 

** 정렬 완료 배열인 result[]배열에 원소를 넣을 때

input[i]-Math.abs(min) 을 하여 저장해야 처음 입력받은(음수를 포함한) 수가 된다. 

 

 

 

 

1. 산술평균

처음 입력받을 때 총합을 구하고, N으로 나눈다.

소수점 이하 첫째 자리에서 반올림해야 하기 때문에 - Math.round()를 이용한다.

 

2. 중앙값

정렬 후에 중앙값을 출력한다.

 

3. 최빈값

카운팅 정렬 과정 중 - counting[]배열의 누적합 계산을 하기 전에 최빈값을 구한다.

숫자의 횟수를 저장한 counting[]배열 원소 중에서 최대값을 구한다.

최대값과 counting[i]가 같다면, 최빈값 중 하나를 의미하게 된다.

max == counting[i] 인 값들을 list에 저장하여, 앞에서 두 번째 수를 출력한다.

 

4. 범위

정렬 후에 마지막 원소-첫 번째 원소 를 출력한다.

 

 

'1d-1c > BOJ' 카테고리의 다른 글

3273_두 수의 합 (JAVA)  (0) 2020.11.07
1931_회의실배정 (JAVA)  (0) 2020.11.05
10989_수 정렬하기3 (JAVA)  (0) 2020.11.03
2751_수 정렬하기2 (JAVA)  (0) 2020.10.29
1436_영화감독 슘 (JAVA)  (0) 2020.10.29