2 minute read

2019 KAKAO BLIND RECRUITMENT

Category : 구현, Map

  • 제한 사항을 잘 분석해서 구현해야 하는 문제
  • 테스트케이스 1번, 25번은 N + 1 제한사항 조건에 해당되는 케이스 같다고 추측 (인덱스 체크)

Flow.

  • 스테이지를 클래스로 만들어 스테이지 객체 안에 실패합계 와 실패율 계산 로직을 만들었습니다.
  • 각 스테이지 번호를 Key, 스테이지 객체를 Value 로 가지는 해쉬맵을 선언했습니다.
    • stageMap은 스테이지 정보를 업데이트 및 조회하는 DB 용도로 사용됩니다.
  • 핵심로직의 전제조건은 stages 배열의 오름차순 정렬입니다.
    • 정렬 후 stages 배열을 반복문으로 탐색
    • 조건 1) stages 배열의 요소가 다음 요소와 다른 경우
      • 해당 stage 가 탐색이 끝났음으로 실패율을 업데이트 해줍니다.
      • 게이머의 인원 수 또한 해당 스테이지의 실패 합계로 빼줍니다. (다음 스테이지에 참여 불가)
    • 조건 2) stages 배열의 요소가 다음 요소와 같은 경우
      • 해당 stage 가 탐색이 끝나지 않았음으로 실패율은 업데이트 하지 않습니다.
    • 조건 3) 현재 요소와 다음 요소 비교 조건으로 인한 마지막 인덱스에 대한 조건 (else)
      • 마지막 인덱스임으로 해당 stage 탐색이 끝났음으로 실패율을 업데이트 해줍니다.
  • N 이 5 일 경우 스테이지 1~5 까지의 실패율 만 필요하므로 반복문 첫번째에 탈출조건을 만들어주었습니다.
  • 원하는 스테이지 범위(N) 의 스테이지의 실패율을 비교 정렬해서 배열로 리턴해줍니다.

Code.

import java.util.*;

public class 실패율 {
    public static void main(String[] args) {
        int N = 5;
        int N2 = 4;
        int N3 = 2;
        int N4 = 3;
        int N5 = 7;
        int[] stages = {2, 1, 2, 6, 2, 4, 3, 3};
        int[] stages2 = {4, 4, 4, 4, 4};
        int[] stages3 = {1, 1, 1, 1};
        int[] stages4 = {1, 2, 2, 1, 3};
        int[] stages5 = {2, 4, 4, 4, 4};

        System.out.println(Arrays.toString(solution(N, stages)));
        System.out.println(Arrays.toString(solution(N2, stages2)));
        System.out.println(Arrays.toString(solution(N3, stages3)));
        System.out.println(Arrays.toString(solution(N, stages4)));
        System.out.println(Arrays.toString(solution(N4, stages5)));
    }

    public static int[] solution(int N, int[] stages) {
        Map<Integer, Stage> stageMap = new HashMap<>();
        for (int i = 1; i <= N + 1; i++) {
            stageMap.put(i, new Stage(i, 0, 0));
        }
        
        Arrays.sort(stages);
        // 게임의 게이머 수
        int gamers = stages.length;
        for (int i = 0; i < stages.length; i++) {
            // N 이 5 라면 Stage 1 ~ 5 까지의 실패율만 가지고 결과를 리턴한다.
            if (stages[i] > N) {
                break;
            }
            int curStageCaseByUser = stages[i];
            Stage stage = stageMap.get(curStageCaseByUser);
            // 현재 유저의 스테이지가 배열의 다음 유저의 스테이지와 다른 경우, 스테이지의 실패합계를 증가 & 실패율을 최종 계산한다.
            // 스테이지 맵에 업데이트 해준다.
            // 최종 계산 후 게이머의 수 또한 해당 스테이지의 실패 합계로 빼준다.
            if (i < stages.length - 1 && curStageCaseByUser != stages[i + 1]) {
                stage.increaseFailSum();
                stage.calculateFailRate(gamers);
                stageMap.put(curStageCaseByUser, stage);
                gamers -= stage.getFailSum();
                // 현재 유저의 스테이지가 배열의 다음 유저의 스테이지와 같은 경우, 스테이지의 실패합계를 증가한다.
                // 스테이지 맵에 업데이트 해준다.
                // 게이머의 수는 배열이 정렬되어 있음으로 다음 유저의 스테이지와 같은 경우 감산을 하지 않는다.
            } else if (i < stages.length - 1 && curStageCaseByUser == stages[i + 1]) {
                stage.increaseFailSum();
                stageMap.put(curStageCaseByUser, stage);
            } else {
                // stages 배열의 마지막 인덱스에 도달 해당 스테이지의 실패합계를 증가 & 실패율을 최종 계산한다.
                // 스테이지 맵에 업데이트 해준다.
                stage.increaseFailSum();
                stage.calculateFailRate(gamers);
                stageMap.put(curStageCaseByUser, stage);
            }
        }

        return printSortedResult(N, stageMap);
    }

    private static int[] printSortedResult(int N, Map<Integer, Stage> stageMap) {
        int[] answer = new int[N];
        List<Map.Entry<Integer, Stage>> entryList = new ArrayList<>(stageMap.entrySet());
        entryList.sort((e1, e2) -> Double.compare(e2.getValue().failRate, e1.getValue().failRate));
        for (int i = 0; i < N; i++) {
            answer[i] = entryList.get(i).getKey();
        }
        return answer;
    }

    public static class Stage {

        private int stageNumber;

        private int failSum;

        private double failRate;

        public Stage(int stageNumber, int failSum, double failRate) {
            this.stageNumber = stageNumber;
            this.failSum = failSum;
            this.failRate = failRate;
        }

        public void increaseFailSum() {
            this.failSum++;
        }

        public void calculateFailRate(int gamers) {
            this.failRate = (double) this.failSum / gamers;
        }

        public int getFailSum() {
            return this.failSum;
        }
    }
}

Leave a comment