3 분 소요



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



📌 문제

문제 유형

  • 수학
  • 구현
  • 정렬


문제 설명

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

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

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


입출력 예시

입력

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

5
1
3
8
-2
2

출력

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

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

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

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

2
2
1
10



🔍 문제 풀이 (최빈값 구하기)

  • 정수 배열에 입력값을 저장하고, 정렬 후 중앙값과 범위를 구함
  • HashMap을 통해 등장 횟수를 세고, 최빈값 후보들을 리스트에 모아 정렬
  • 최빈값이 2개 이상이면 두 번째로 작은 값 출력, 아니면 첫 번째 값 출력
  • 평균은 소수점 첫째 자리에서 반올림 처리 (Math.round() 사용)


Collections.max(map.values())

Collections.max(map.values())컬렉션(이 문제에서는 map의 value들 중) 에서 가장 큰 값을 찾는 메서드이다.

  • map.values()
    • → Map에 저장된 모든 값(value) 들을 가져온다.
    • e.g., {1=2, 2=3, 3=3}이면 map.values()는 `[2, 3, 3].


  • Collections.max(...)
    • → 주어진 값들 중 최댓값을 리턴한다.


map이 아래와 같다고 할 때:

{10=2, 20=3, 30=1, 40=3}

→ 각 숫자(10, 20, 30, 40)가 나온 횟수(빈도)를 저장한 것
→ 가장 많이 나온 횟수(최빈값의 빈도수)는 3

이를 얻기 위해 사용하는 게 Collections.max(map.values())


그럼 최빈 값이 여러개일 경우 어떻게하지?

여러 개일 수 있으니 리스트에 담고 정렬 후 조건 처리한다.

int maxFreq = Collections.max(map.values());
List<Integer> modeList = new ArrayList<>();

for (int key : map.keySet()) {
    if (map.get(key) == maxFreq) {
        modeList.add(key);
    }
}

Collections.sort(modeList); // 오름차순 정렬
int mode = modeList.size() >= 2 ? modeList.get(1) : modeList.get(0); // 두 번째로 작은 값


entrySet()과 Map.Entry

코드 의미
Map.Entry<K, V> Map의 key-value 한 쌍을 표현하는 객체
map.entrySet() Map 안의 모든 entry(key, value)를 Set으로 반환
entry.getKey() 해당 쌍의 key
entry.getValue() 해당 쌍의 value


entrySet()

  • entrySet()Map에 저장된 (key, value) 쌍 전체를 Set 형태로 반환한다.
  • 즉, Map을 반복문으로 순회할 때 사용하는 대표적인 방식이다.
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    int key = entry.getKey();
    int value = entry.getValue();
    // key: 숫자, value: 등장 횟수
}


왜 사용할까?

최빈값을 구하기 위해선 모든 (숫자, 횟수) 쌍을 하나씩 검사해야 한다.

이때 entrySet()을 사용하면 key와 value를 동시에 쉽게 꺼낼 수 있다.

// value가 maxFreq인 key들만 리스트에 모으기
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    if (entry.getValue() == maxFreq) {
        modes.add(entry.getKey());
    }
}



💻 전체 코드

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

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[] nums = new int[n];
        int sum = 0;

        for (int i = 0; i < n; i++) {
            nums[i] = Integer.parseInt(br.readLine());
            sum += nums[i];
        }

        Arrays.sort(nums);

        int avg = (int) Math.round((double) sum / n);
        int center = nums[n / 2];
        int range = nums[n - 1] - nums[0];

        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        int maxFreq = Collections.max(map.values());

        List<Integer> modes = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            if (entry.getValue() == maxFreq) {
                modes.add(entry.getKey());
            }
        }

        Collections.sort(modes);
        int mode = (modes.size() > 1) ? modes.get(1) : modes.get(0);

        System.out.println(avg);
        System.out.println(center);
        System.out.println(mode);
        System.out.println(range);
    }
}



💭 배운 점

  • 최빈값을 구할 때 단순히 Map에서 찾는 것만으로는 부족하고,
    최빈값 후보들을 List에 모아 정렬한 후 두 번째로 작은 값을 출력해야 한다.
  • Map.EntryentrySet()을 통해 (key, value) 쌍을 순회할 수 있다.
  • Math.round()를 쓰면 산술평균을 정확하게 반올림할 수 있다.



🔁 복습 템플릿

Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
    map.put(num, map.getOrDefault(num, 0) + 1);
}

int maxFreq = Collections.max(map.values());

List<Integer> modes = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    if (entry.getValue() == maxFreq) {
        modes.add(entry.getKey());
    }
}
Collections.sort(modes);
int mode = (modes.size() > 1) ? modes.get(1) : modes.get(0);


카테고리:

업데이트:

댓글남기기