[Baekjoon] 2108번: 통계학

2023. 3. 20. 14:23Computer Sciences/Problem Solve

https://www.acmicpc.net/problem/2108

 

2108번: 통계학

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

www.acmicpc.net

문제 설명

정수 N개가 주어진다. 이 숫자들에 대해 통계값을 출력해야 한다(단, N은 홀수이며 N의 절댓값은 절대 4000을 넘지 않는다).

  • 산술 평균: N개의 수들의 합을 N으로 나눈 값
  • 중앙값: N개의 수들을 오름차순으로 정렬했을 경우 그 중앙에 위치하는 값
  • 최빈값: N개의 수들 중 가장 많이 나타나는 값
  • 범위: N개의 수들 중 최댓값과 최솟값의 차이

 

출력 형식은 다음과 같다.

  • 첫째 줄에는 산술 평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.
  • 둘째 줄에는 중앙값을 출력한다.
  • 셋째 줄에는 최빈값을 출력한다. 여러 개가 있는 경우 최빈값 중 두 번째로 작은 값을 출력한다.
  • 넷째 줄에는 범위를 출력한다.

풀이 방법

산술 평균은 stream을  사용하여 해결했다.

Math.round(Arrays.stream(nums).average().getAsDouble());

중앙값, 범위는 정렬만 하면 해결할 수 있기 때문에 정렬을 사용했다.

// 오름차순 정렬
Arrays.sort(nums);

// 중간값
nums[N / 2];

// 범위
nums[N - 1] - nums[0];

최빈값은 따로 구해야 하기 때문에 Map을 사용하여 해결했다.

Map<Integer, Integer> map = new HashMap<>();

for (int i = 0; i < N; i++) {
    nums[i] = Integer.parseInt(br.readLine());
    if (map.get(nums[i]) != null) {
        map.put(nums[i], map.get(nums[i]) + 1);
    } else {
        map.put(nums[i], 1);
    }
}

// 맵에 저장된 숫자 중 value가 가장 큰 값이 최빈값
Map.Entry<Integer, Integer> mode =
                map.entrySet().stream().max(Comparator.comparing(entry -> entry.getValue())).get();

List<Map.Entry<Integer, Integer>> entries = map.entrySet().stream()
                // 최빈값이 같은 값을 필터링
                .filter(entry -> entry.getValue().equals(mode.getValue()))
                // 최빈값이 같은 경우 숫자 기준 오름차순 정렬
                .sorted((e1, e2) -> e1.getValue().equals(e2.getValue())
                        ? e1.getKey().compareTo(e2.getKey())
                        : e1.getValue().compareTo(e2.getValue()))
                .collect(Collectors.toList());
                
// 최빈값이 한 개인 경우 그 수를 출력하고, 아니라면 두 번째로 작은 수 출력
sb.append(entries.size() == 1 ? entries.get(0).getKey() : entries.get(1).getKey())
                .append("\n");

전체 코드는 다음과 같다.

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

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[] nums = new int[N];

        Map<Integer, Integer> map = new HashMap<>();

        for (int i = 0; i < N; i++) {
            nums[i] = Integer.parseInt(br.readLine());
            if (map.get(nums[i]) != null) {
                map.put(nums[i], map.get(nums[i]) + 1);
            } else {
                map.put(nums[i], 1);
            }
        }

        Arrays.sort(nums);

        Map.Entry<Integer, Integer> mode =
                map.entrySet().stream().max(Comparator.comparing(entry -> entry.getValue())).get();

        List<Map.Entry<Integer, Integer>> entries = map.entrySet().stream()
                .filter(entry -> entry.getValue().equals(mode.getValue()))
                .sorted((e1, e2) -> e1.getValue().equals(e2.getValue())
                        ? e1.getKey().compareTo(e2.getKey())
                        : e1.getValue().compareTo(e2.getValue()))
                .collect(Collectors.toList());

        StringBuilder sb = new StringBuilder();
        // 산술 평균
        sb.append(Math.round(Arrays.stream(nums).average().getAsDouble())).append("\n");
        // 중간값
        sb.append(nums[N / 2]).append("\n");
        // 최빈값
        sb.append(entries.size() == 1 ? entries.get(0).getKey() : entries.get(1).getKey())
                .append("\n");
        // 범위
        sb.append(nums[N - 1] - nums[0]);

        System.out.print(sb);
    }
}