백준 알고리즘 문제(81) - 통계학

Code_Alpacat·2021년 9월 12일
0

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

첫째줄에 수의 개수 홀수 N이 주어지고, 그 다음 정수들이 N개 주어진다. 입력되는 정수의 절대값은 4000이하다.

  1. 산술평균은 첫째 자리에서 반올림한 값을 출력한다. Math.round를 이용한다.
  2. 중앙값을 출력한다.
  3. 최빈값을 출력한다. 여러 개인 경우 두 번째로 작은 값 출력.
  4. 범위를 출력한다.

차례대로 생각해봐야한다. 음수가 포함되어 있으므로 8001의 공간을 가지는 배열을 만든다.

  1. 산술평균은 정렬이 필요없으므로 바로 식을 만들면 된다.
  2. 중앙값부터는 정렬하고 N/2 + 1번째 값을 출력한다.
  3. 최빈값은 호출될때마다 1씩 값을 늘려 가장 큰 값을 출력한다. 두 배열의 값이 같다면, 두 배열 중에 더 뒤에 있는 배열의 index값을 출력하고, 세 배열의 값이 같다면 처음 나온 배열 다음 값의 index를 출력한다.
  4. 정렬한 배열에서 가장 뒤의 배열 index에서 맨 앞 index를 뺀다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class java_io {
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	public static void main(String[] args) throws IOException {
		int N = Integer.parseInt(br.readLine());
		int[] arr = new int[8001];
		//절대값이 4000이므로 4000이 시작점이다.
		for(int i=0; i<N; i++) {
			arr[Integer.parseInt(br.readLine())+4000]++;
		}
		
		
		//정렬된 index값들을 저장해주기위한 공간
		int[] arr_copy = new int[8001];
		for(int i=0; i<8001; i++) {
			arr_copy[i] = arr[i];
		}
		
		int[] arr_index = new int[N];
		int num =0;
		for(int i=1; i<8001; i++) {
			
			while(arr[i]>0) {
				arr_index[num] = i-4000;
				arr[i]=0;
				num++;
			}

		}
		
		StringBuilder sb = new StringBuilder();
		
		//1. 산술평균
		double avg = 0;
		for(int i=0; i<arr_index.length; i++) {
			avg +=arr_index[i];
		}
		sb.append((int)Math.round(avg/(double)N)).append('\n');
		
		//2. 중앙값
		sb.append(arr_index[N/2]).append('\n');
		//3. 최빈값
			int mode =10000;
			int mode_max = 0;
			boolean flag = false;
				
			for(int i = arr_index[0]+4000; i<=arr_index[N-1]+4000; i++) {
				if(arr_copy[i]>0) {
				if(mode_max < arr_copy[i]) {
					mode_max =arr_copy[i];
					mode = i-4000;
					flag = true;
				}
				
					else if(mode_max == arr_copy[i] && flag ==true) {
						mode = i-4000;
						flag =false;
					}
			}
		}
				sb.append(mode).append('\n');
				
				
		
		//4. 범위
		sb.append(arr_index[N-1] - arr_index[0]).append('\n');
		System.out.print(sb);
	}
	
	
}

방향을 잡을 때, 풀기 힘든 방향을 잡아서 틀리긴했지만 음수 값을 입력받을 때, 문제가 발생했다. 선 정렬 후에, 값들을 구한게 실패요인이었다. 처음부터 끝까지, 값을 찾아가며 순서를 정해서 푸는 방법을 찾아서 이해하니, 코드를 어떻게 구현할지 구조적인 부분을 먼저 생각해야만 한다는 것을 깨달았다. 아래는 참고한 답안이다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class java_io {
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	public static void main(String[] args) throws IOException {

		int N = Integer.parseInt(br.readLine());
		
		// 입력값의 범위 : -4000 ~ 4000
		int[] arr = new int[8001];
		
		/*
		 *  sum = 총 합계 
		 *  max = 최댓값
		 *  min = 최솟값 
		 *  median = 중앙값
		 *  mode = 최빈값 
		 */
		int sum = 0;
		int max = Integer.MIN_VALUE;
		int min = Integer.MAX_VALUE;
		// median 과 mode 는 -4000~4000 을 제외한 수로 초기화하면 된다.
		int median = 10000;
		int mode = 10000;
		
		for(int i = 0; i < N; i++) {
			int value = Integer.parseInt(br.readLine());
			sum += value;
			arr[value + 4000]++;
		
			if(max < value) {
				max = value;
			}
			if(min > value) {
				min = value;
			}
		}
		
		
		// 순회 
		int count = 0;	// 중앙값 빈도 누적 수 
		int mode_max = 0; 	// 최빈값의 최댓값  
		
		// 이전의 동일한 최빈값이 1번만 등장했을경우 true, 아닐경우 false
		boolean flag = 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);	// 범위 
	}
 
}

출처 : Stranger's lab

profile
In the future, I'm never gonna regret, cuz I've been trying my best for every single moment.

0개의 댓글