[java][boj][s4] 2108. 통계학
728x90
 

2108번: 통계학

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

www.acmicpc.net

문제

수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.

  1. 산술평균 : N개의 수들의 합을 N으로 나눈 값
  2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
  3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값
  4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이

N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.

입력

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

출력

첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.

둘째 줄에는 중앙값을 출력한다.

셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.

넷째 줄에는 범위를 출력한다.

풀이

/*
 * 1. 첫째줄에 수의 개수 N
 * 2. N개의 정수
 * 
 * >> 산술평균: 평균 >> String.format 사용해서 반올림
 * >> 중앙값: 오름차순 정렬한 뒤 중앙에 위치하는 값 >> 오름차순 정렬한 뒤 가운데값 뽑기
 * >> 최빈값: 가장 많이 나타나는 값(같을 경우 두번째로 작은 숫자를 출력) >> 배열에 넣어서 세기
 * >> 범위: 최댓값과 최솟값의 차이 >> 오름차순 정렬한 뒤 제일 큰 값에서 제일 작은 값 빼기
 */

다른 건 괜찮았는데 최빈값 구하는게 어려웠다 받은 num을 인덱스로 써서 배열에 저장한 다음, 값으로 빈도수를 저장해 max 값을 출력하는 방식으로 했는데 음수를 인덱스에 담을 수 없다 보니까 절댓값으로 넣는 과정에서 이러저러하게 오류가 자꾸 생겼다 처음에는 for문으로 음수와 양수를 한번에 계산했지만 그렇게 하면 안돼서 다시 음수 빈도수를 먼저 계산하고, 양수 빈도수를 나중에 계산하는 식으로 바꿨다

코드

package lv12_정렬;

import java.util.*;
import java.io.*;

public class s4_2108_통계학 {

	public static void main(String[] args) throws Exception {
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		
		int N = Integer.parseInt(br.readLine());
		int[] nums = new int[N];
		int[][] mode = new int[2][4001]; //0일때 양수, 1일때 음수(최빈값 셀 때 쓰기)
		
		double sum = 0;
		
		for(int i = 0; i<N; i++) {
			int num = Integer.parseInt(br.readLine());
			
			sum += num; //산술평균 구할 때 쓰기
			nums[i] = num; //중앙값, 범위 구할때 쓰기
			
			if(num>=0) mode[0][num]++; //num이 양수면 [0] 배열 해당 숫자 인덱스에 빈도 저장
			else mode[1][(-1)*num]++; //num이 음수면 [1] 배열 해당 숫자 절대값 인덱스에 빈도 저장 
		}
		
		int max = 0;
		int maxResult = 0;
		boolean b = false;
		
		//빈도수
		for(int i = 4000; i >= 0; i--) { //음수는 절대값이 클수록 작기 때문에 큰 수부터 돌리기
			if(max < mode[1][i]) { //max값보다 빈도수 높으면
				max = mode[1][i]; //max에 저장
				maxResult = (-1)*i; //인덱스를 절대값으로 저장했기 때문에 다시 -1 곱해줌
				b = true;
			} else if(b==true && max == mode[1][i]) { //같은 빈도수가 있으면 두번째 값 저장
				maxResult = (-1)*i;
				b = false; //세번째 값부터 저장할 수 없게 boolean false로 바꿈
			}
		}
		
		for(int i = 0; i < 4001; i++) { //양수 최빈값 구하기
			if(max < mode[0][i]) {
				max = mode[0][i];
				maxResult = i;
				b = true;
			} else if(b==true && max == mode[0][i]) {
				maxResult = i;
				b = false;
			}
		}
		
		//중앙값, 범위 구하기 위해 오름차순 정렬
		Arrays.sort(nums);
		
		sb.append(String.format("%.0f",sum/N)).append("\n").append(nums[N/2]).append("\n").append(maxResult).append("\n").append(nums[N-1]-nums[0]);
		System.out.println(sb);
	}
}

결과

 

#자바 #java #boj #백준 #알고리즘

728x90