실패율 (2019 KAKAO BLIND RECRUITMENT)

HeeSeong·2021년 6월 8일
0

프로그래머스

목록 보기
62/97
post-thumbnail

🔗 문제 링크

https://programmers.co.kr/learn/courses/30/lessons/42889


❔ 문제 설명



슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스테이지 차이가 너무 큰 것이 문제였다.

이 문제를 어떻게 할까 고민 한 그녀는 동적으로 게임 시간을 늘려서 난이도를 조절하기로 했다. 역시 슈퍼 개발자라 대부분의 로직은 쉽게 구현했지만, 실패율을 구하는 부분에서 위기에 빠지고 말았다. 오렐리를 위해 실패율을 구하는 코드를 완성하라.

실패율 = 스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수

전체 스테이지의 개수 N, 게임을 이용하는 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열 stages가 매개변수로 주어질 때, 실패율이 높은 스테이지부터 내림차순으로 스테이지의 번호가 담겨있는 배열을 return 하도록 solution 함수를 완성하라.


⚠️ 제한사항


  • 스테이지의 개수 N은 1 이상 500 이하의 자연수이다.

  • stages의 길이는 1 이상 200,000 이하이다.

  • stages에는 1 이상 N + 1 이하의 자연수가 담겨있다.

  • 각 자연수는 사용자가 현재 도전 중인 스테이지의 번호를 나타낸다.

  • 단, N + 1 은 마지막 스테이지(N 번째 스테이지) 까지 클리어 한 사용자를 나타낸다.

  • 만약 실패율이 같은 스테이지가 있다면 작은 번호의 스테이지가 먼저 오도록 하면 된다.

  • 스테이지에 도달한 유저가 없는 경우 해당 스테이지의 실패율은 0 으로 정의한다.



💡 풀이 (언어 : Java & Python)


실패율 정렬하는데 필요한 기준이 두가지(실패율, 같을시 스테이지 숫자)이므로 따로 객체를 생성해서 두가지 기준을 받아주고 Comparator를 구현해서 정렬 기준으로 준다. 유저들의 스테이지 배열을 한번 돌아서 각 스테이지 별 유저들의 수를 기록해주고, 그 배열을 다시 돌면서 실패율을 계산해서 리스트에 넣어준다. 그 리스트를 객체와 Comparator를 이용해서 정렬해주고 실패율대로 정렬한 리스트의 원소의 스테이지 수로 정답 배열을 만들어주면 끝이다.

Java

public class Solution {

    class FailInfo {
        private int stage;
        private double failRate;

        private FailInfo(int stage, double failRate) {
            this.stage = stage;
            this.failRate = failRate;
        }
    }

    public int[] solution(int N, int[] stages) {
        int[] answer = new int[N];
        // 총 실패율 계산 대상 유저 수
        int total = stages.length;
        // 모두 클리어한 유저로 인해 길이가 +1
        int[] stageUser = new int[N+1];
        // 각 스테이지 별 유저 수 배열 생성
        for (int s : stages)
            stageUser[s-1]++;
        // 계산한 실패율을 스테이지별로 보관할 리스트 (인덱스 = 스테이지 숫자-1)
        ArrayList<FailInfo> rateList = new ArrayList<>();
        // 실패율 계산 (stageUser보다 인덱스 크기 1작은 N까지 - 모두 클리어한 사람은 배열 포함 x
        for (int i = 0; i < N; i++) {
            // 해당 스테이지의 유저 수가 0인 경우 실패율 0 처리
            if (stageUser[i] == 0)
                rateList.add(new FailInfo(i+1, 0));
            else
                rateList.add(new FailInfo(i+1,  (double) stageUser[i]/total));
            // 앞의 스테이지 도달한 사람 수를 전체 수에서 뺀 수가 다음 실패율 분모임
            total -= stageUser[i];
        }
        // rateList를 정렬해주기
        Collections.sort(rateList, new Comparator<FailInfo>() {
            @Override
            public int compare(FailInfo o1, FailInfo o2) {
                if (o1.failRate < o2.failRate)
                    return 1;
                else if (o1.failRate > o2.failRate)
                    return -1;
                else {
                    if (o1.stage < o2.stage)
                        return -1;
                    // 여기서 스테이지 숫자가 같을리는 없다
                    else
                        return 1;
                }
            }
        });
        // 정답 배열 만들기
        for (int i = 0; i < N; i++)
            answer[i] = rateList.get(i).stage;
        return answer;
    }
}

Python

def solution(N, stages):
    # 이미 계산한 숫자인지 체크
    check = [True for i in range(N)]
    answer = []
    countList = []
    for s in stages:
        if s != N+1 and check[s-1]:
            arriveList = list(filter(lambda x : x >= s, stages))        
            failList = list(filter(lambda x : x == s, stages))
        
            failRate = len(failList) / len(arriveList)
            countList.append((s , failRate))
            check[s-1] = False
        
    # 실패율이 높은 순으로 내림차순 정렬, 실패율 같으면 스테이지 숫자 오름차순 정렬
    countList.sort(key = lambda x : (-x[1], x[0]))
    
    for c in countList:
        answer.append(c[0])
        
    noNum = check.count(True)
    for i in range(noNum):
        idx = check.index(True)
        answer.append(idx+1)
        check[idx] = False
        
    return answer
profile
끊임없이 성장하고 싶은 개발자

0개의 댓글