코딩테스트/BOJ

[BOJ] 2108 통계학 - JAVA

5월._. 2022. 2. 23.
728x90

1. 문제

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

 

2108번: 통계학

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

www.acmicpc.net

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

2. 풀이

  • 평균 : 자바는 반올림을 할 때 -0이 생기는 경우도 있다. 따라서 평균을 구한 뒤 -0이라면 0으로 바꿔주는 작업이 필요하다.
  • 중앙값 : map으로 받았기 때문에 entryset으로 만든 리스트를 key기준 오름차순으로 정렬한 뒤 숫자를 하나하나 세 가면서 N/2보다 같거나 커질때 반복을 멈춘다.
  • 범위 : entrylist에서 첫 번째 값과 마지막 값을 뺀다.
  • 최빈값 : entrylist를 다시 value기준으로 정렬한다. 앞에서 한 번 key값으로 정렬했기 때문에 value가 같다면 key오름차순으로 정렬된다. entrylist 0번값을 먼저 저장하고나서 1번값이 있다면 value를 비교한다. 같을때만 1번 값을 최빈값으로 삼는다. 
import java.io.*;
import java.util.*;

public class BOJ_2108_통계학 {
   public static void main(String[] args) throws NumberFormatException, IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      int N = Integer.parseInt(in.readLine());

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

      int sum = 0;
      for (int i = 0; i < N; i++) {
         int num = Integer.parseInt(in.readLine());
         nums.put(num, nums.getOrDefault(num, 0) + 1);
         sum += num;
      }

      // 평균
      int avg = (int)Math.round((double) sum / N);
      if(avg==-0) avg = 0;

      // entryset으로 만든 list
      List<Map.Entry<Integer, Integer>> entrylst = new ArrayList<>(nums.entrySet());

      // key정렬:오름차순
      entrylst.sort(Entry.comparingByKey());

      // 중앙값
      int mid = 0;
      int count = 0;
      for(int i=0;i<entrylst.size();i++) {
         count+=entrylst.get(i).getValue();
         if(count>N/2) {
            mid = entrylst.get(i).getKey();
            break;
         }
      }
      
      //범위
      int range = entrylst.get(entrylst.size()-1).getKey() - entrylst.get(0).getKey();

      // value정렬:내림차순
      entrylst.sort(Entry.comparingByValue((o1, o2) -> o2.intValue() - o1.intValue()));

      // 최빈값 - entrylst.size() 1보다 크면 비교해서 두번째 값 넣기
      int mode = entrylst.get(0).getKey();
      if (entrylst.size() > 1 && entrylst.get(0).getValue().equals(entrylst.get(1).getValue())) {
         mode = entrylst.get(1).getKey();
      }

      BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
      out.write(String.format("%d\n%d\n%d\n%d\n", avg, mid, mode, range));

      out.flush();

   }
}

3. 결과

여러 번 제출했는데, 위의 코드는 572ms걸린 코드다.

댓글