코딩테스트/백준

[백준] 2108 통계학

민톨이 2024. 12. 29. 19:34
728x90

 

혼자 풀다가 잘 안풀려서 거의 남의 코드를 보고 참고하면서 뜯어 고쳤지만 업로드 해봅디다

https://st-lab.tistory.com/108

 

[백준] 2108번 : 통계학 - JAVA [자바]

www.acmicpc.net/problem/2108 2108번: 통계학 첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다. www.acmicpc.net 문

st-lab.tistory.com

항상 백준 풀다 안풀려서 번호명 + 자바 치면 최상단에 뜨는 st-lab님의 코드를 참고하였습니다

 

(중앙값과 범위 구하기는 괜찮았는데 산술평균 쉽게 보다가 약간 실수하고 최빈값에선 아예 어리버리깠음)

package sort;

import java.util.Scanner;

public class Boj2108 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        //입력값 범위: -4000 ~ 4000 [8001]
        int[] arr = new int[8001];

        int sum = 0;
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        //중간값과 최빈값은 -4000~4000 을 제외한 수로 초기화
        int median = 10000;
        int mode = 10000;

        for (int i = 0; i < n; i++) {
            int value = sc.nextInt();
            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];
                    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);
    }
}

 

 

📌 최빈값 코드 설명

최빈값(mode) 구하는 과정:

  1. arr[i] > 0:
    • arr[i]는 숫자 i - 4000의 빈도를 나타낸다. 이 조건은 배열에 그 숫자가 한 번이라도 등장했다면, 그 숫자의 빈도를 확인하는 과정
  2. if (count < (n + 1) / 2):
    • 이 조건은 중앙값(median)을 찾기 위한 조건. count는 배열의 원소 중 중앙값이 될 때까지 나온 숫자들의 빈도 합이다.
    • (n + 1) / 2는 중앙값의 위치를 나타내는데, 홀수 개의 숫자에서 정확히 가운데 값을 찾는 방법
    • 중앙값을 찾을 때까지 빈도를 누적하여 count가 (n+1) / 2에 도달하면, 그 숫자를 median으로 지정
  3. else if (mode_max == arr[i] && flag == true):
    • mode_max는 그 숫자가 가장 자주 등장하는 빈도를 추적합니다. 즉, 최빈값이 업데이트될 때마다, 가장 큰 빈도수를 저장해둠
    • flag == true는 이전에 최빈값을 찾을 때 중복을 방지하는 역할을 한다. mode_max == arr[i]인 경우(최빈값이 동일한 빈도를 갖는 경우) 한 번만 최빈값을 업데이트하도록 하는 부분임
  4. mode = i - 4000:
    • i - 4000은 원래 값으로 복원한 숫자를 mode로 저장. 예를 들어, i가 4000이면 i - 4000은 0, i가 8000이면 i - 4000은 4000이 됨미다
  5. flag = false:
    • flag는 최빈값을 찾았다는 것을 표시하는 역할을 합니다. flag가 true일 때는 첫 번째 최빈값을 찾았고, 두 번째로 동일한 빈도수가 나오면 그 값을 mode로 지정하고 flag를 false로 변경합니다. 이렇게 함으로써 두 번째로 작은 최빈값을 구할 수 있습니다.

 

==>>> 각 숫자의 빈도를 카운트하여 최댓값을 구하고, 그 빈도수가 여러 번 나오는 경우 두 번째로 작은 최빈값을 출력

 
 
 
 
 
 

 

 

'코딩테스트 > 백준' 카테고리의 다른 글

[백준] 듣보잡 - Python  (1) 2025.05.22
[백준] 1920 수 찾기  (4) 2024.12.25
[백준] 5585 거스름돈 - 그리디 알고리즘  (2) 2024.10.30
[백준] 5622 다이얼  (0) 2024.10.29
[백준] 2675 문자열 반복  (1) 2024.10.29