Java/백준알고리즘

[Java] 백준알고리즘 #2108 통계학

Sehyeok20 2023. 10. 18. 18:38
반응형

백준알고리즘 #2108 통계학
백준알고리즘 #2108 통계학

 

입력받은 값들의 산술평균, 중앙값, 최빈값, 범위를 출력하는 문제.

 

1. 산술평균

산술평균은 입력받은 값들을 차례로 더한 후, 수의 개수를 나누면 간단하다.

다만 단순히 / 로 나누는 것이 아닌 Math.round함수를 이용해서 반올림된 값을 구할 수 있다.

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
int[] ary = new int[n];

int sum = 0; // 평균값을 위한 합계

for (int i = 0; i < n; i++) {
    ary[i] = Integer.parseInt(br.readLine());
    sum += ary[i]; // 입력값 모두 더하기
}

... // 중략

System.out.println(Math.round((double) sum / n)); // 평균값

 

 

2. 중앙값

입력받은 수들을 오름차순 혹은 내림차순으로 나열한 후 중앙값을 구하면 간단하다.

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
int[] ary = new int[n];

int sum = 0; // 평균값을 위한 합계

for (int i = 0; i < n; i++) {
    ary[i] = Integer.parseInt(br.readLine());
    sum += ary[i]; // 입력값 모두 더하기
}

... // 중략
Arrays.sort(ary);
System.out.println(ary[n / 2]); // 중앙값

수를 담은 배열을 정렬하기 위해 지금까지 자주 사용했던 선택정렬을 사용해서 문제를 해결하면 시간 초과 에러가 나온다.

때문에 이번에는 Arrays.sort 함수를 사용했는데 이에 대해서는 나중에 자세히 알아보자.

 

 

3. 최빈값

이 부분이 가장 어려울 듯 한데, 조건에서 최빈값이 여러개라면 최빈값 중 두번째로 작은 수를 출력한다 는 조건이 까다로워보인다.

 

최빈값을 찾기 위해서는 각 숫자가 몇 번 사용되었는지 확인하면 되는데, 그 중 가장 작은 수는 어렵지 않게 구할 수 있다.

다만, 두번째로 작은 수를 구하기 위해서는 어떠한 조건을 추가해주어야 하는데, 나는 boolean 변수인 flag를 이용해 이를 구분했다.

int[] count = new int[8001]; // 빈도 수 카운팅 배열
int max = 0; // 카운팅 최대치
int mode = 0; // 최빈값을 담을 변수
boolean flag = false; // 두번째 최빈값 찾기 위한 플래그

for (int i = 0; i < n; i++) {
    ary[i] = Integer.parseInt(br.readLine());
    sum += ary[i]; // 입력값 모두 더하기
    count[ary[i] + 4000]++; // 카운팅 배열의 i(입력값)번째 값 증가

}

Arrays.sort(ary);

for (int i = 0; i < count.length; i++) { // 최빈값 찾기
    if (count[i] > max) {
        mode = i - 4000;
        max = count[i];
        flag = true;
    } else if (count[i] == max && flag == true) {
        mode = i - 4000;
        flag = false;
    }
}
System.out.println(mode); // 최빈값

숫자의 범위만큼인 8001개의 배열을 만든 후, 입력받은 수 +4000번째 (음수를 고려하기 위해) 원소의 값을 증가시켜준다.

입력이 끝난 후, count 배열에는 각 숫자가 몇 번 등장했는지가 저장되어 있을 것이다.

count배열을 반복문으로 확인하여 max보다 count가 크다면 해당 수를 mode에 저장하고 (이 때 - 4000을 해준다) flag를 true로 바꿔준다.이후 count가 max와 같고, flag가 true라면 (같은 횟수만큼 등장했고, 두번째로 작다면) flag를 false로 바꿔준 후 해당 수를 mode에 저장한다.반복문이 끝난 후 mode를 출력해주면 완성.

 

 

4. 범위

2에서 오름차순 으로 정렬했으니, 가장 첫번째 수와 가장 마지막번째 수의 차를 계산하면 된다.

System.out.println(ary[n - 1] - ary[0]); // 범위

 

 

전체 코드는 다음과 같다.

 

// 해설참조 : sehyeok.tistory.com 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int[] ary = new int[n];

        int sum = 0; // 평균값을 위한 합계

        int[] count = new int[8001]; // 빈도 수 카운팅 배열
        int max = 0; // 카운팅 최대치
        int mode = 0; // 최빈값을 담을 변수
        boolean flag = false; // 두번째 최빈값 찾기 위한 플래그

        for (int i = 0; i < n; i++) {
            ary[i] = Integer.parseInt(br.readLine());
            sum += ary[i]; // 입력값 모두 더하기
            count[ary[i] + 4000]++; // 카운팅 배열의 i(입력값)번째 값 증가

        }

        Arrays.sort(ary); // 배열 오름차순 정렬

        for (int i = 0; i < count.length; i++) { // 최빈값 찾기
            if (count[i] > max) {
                mode = i - 4000;
                max = count[i];
                flag = true;
            } else if (count[i] == max && flag == true) {
                mode = i - 4000;
                flag = false;
            }
        }

        System.out.println(Math.round((double) sum / n)); // 평균값
        System.out.println(ary[n / 2]); // 중앙값
        System.out.println(mode); // 최빈값
        System.out.println(ary[n - 1] - ary[0]); // 범위

        br.close();
    }

}

 

반응형