PS/Level1

Programmers School level 1: 실패율

우봉수 2023. 1. 31. 18:54

<풀기 전 생각>

sort()함수를 사용하여 유저들의 클리어 스테이지 정보를 정렬시키고

각 스테이지의 실패율을 float 타입으로 실제로 구하고 차후 반복문을 이용해 높은 순서대로 인덱스를 뽑아 반환 할 계획을 세우고 문제 풀이에 들어 갔다.

 

<중간 문제점>

 float의 표현 범위는 소수 7번째 자리 까지 임으로 그 이상의 자리 수에서 차이가 난 경우는 비교하는게 불가능 하여

1 , 6, 7, 9, 13, 14, 23, 24, 25, 26 에서 오류가 발생하였고

 double 로 고쳐도 Pass가 되지 않아 좀더 고민하게 되었다.

 

<실패한 코드>

class Solution {
    public int[] solutionFail(int N, int[] stages) {
        int[] answer = new int[N];
        int maxPeople = stages.length;
        double[] failureRate = new double[N];
        int i=0; int j=0;
        Arrays.sort(stages); // n*log n
        // 전체 스테이지 탐색
        for(int stage=1;stage<=N;stage++) {
            // 실패율의 분자
            int numerator = 0;
            for (i = 0; i < maxPeople; i++) {
                if(stage==stages[i])
                    numerator++;
                if(stage<stages[i])
                    break;
            }
            // 예외 처리
            if(i==0)
                failureRate[stage] = 0;
            else{
                // 실패율의 분모 (통과한 인원 수)
                int denominator = maxPeople-i+numerator;
                failureRate[stage-1] = (double) numerator/denominator;
            }
        }
        System.out.println("qf");
        for(i=0;i<answer.length;i++) {
            double tmp = -1; int index=-1;
            for (j = 0; j < failureRate.length; j++) {
                if(tmp<failureRate[j]){
                    tmp=failureRate[j];
                    index = j;
                }
            }
            failureRate[index] = -1;
            answer[i] = index+1;
        }
        return answer;
    }

}

 

애초에 비교방식을 실수가 아닌 분자*분모 이런 식으로 정수 끼리 비교할 경우 정확한 비교가 가능하다고 판단하여

코드를 수정했으나 

1 ,6, 7, 13, 23, 24, 25가 계속해서 성공하지 않았고 

 

고민 한 결과 분자가 0이 된 경우 실패율이 0임을 처리하니

최종적으로 23, 24을 제외하고는 pass 하게 되었고

 

추가적으로 고민하다 문제에서 정수의 범위는 1~200000 임을 보게 되었고

int 형으로는 200000 * 200000 의 수를 전부 표현 하는게 불가능 하다는 생각이 들게 되어 

long 타입으로 바꾸어서 푸니 비로서 pass 할 수 있었다.

 

<최종 코드>

시간 복잡도 O(n*m) 공간 복잡도 O(n)

class Solution {
    public int[] solution(int N, int[] stages) {
        // 정수 범위를 벗어나는 경우 때문에 안됨
        int[] answer = new int[N];
        int maxPeople = stages.length;
        // 분자, 분모 순으로 저장
        long[][] failureRate = new long[N][2];
        int i=0; int j=0;
        Arrays.sort(stages); // n*log n
        // 전체 스테이지 탐색
        int numerator,denominator;
        for(int stage=1;stage<=N;stage++) {
            // 실패율의 분자
            numerator = 0;
            for (i = 0; i < maxPeople; i++) {
                if(stage==stages[i])
                    numerator++;
                if(stage<stages[i])
                    break;
            }
            // 실패율의 분모 (통과한 인원 수)
            if(numerator==0)
                denominator=1;
            else
                denominator = maxPeople-i+numerator;
            //failureRate[stage-1] = (float) numerator/denominator;
            failureRate[stage-1][0] = numerator;
            failureRate[stage-1][1] = denominator;
        }
        System.out.println("qf");
        for(i=0;i<answer.length;i++) {
            long tmp[] = {-1,1}; int index=-1;
            for (j = 0; j < failureRate.length; j++) {
                if(tmp[0]*failureRate[j][1]<failureRate[j][0]*tmp[1]){
                    tmp[0]=failureRate[j][0];
                    tmp[1]=failureRate[j][1];
                    index = j;
                }
            }
            failureRate[index][0] = -1;
            failureRate[index][1] = 1;
            answer[i] = index+1;
        }

        return answer;
    }
}

 메모: 우수 풀이를 보니 해당 인터페이스를 구체화 하여 문제를 해결 하였는데 추가 학습할 필요가 있어 보인다.

+ double도 결국에는 소수점 16자리 까지 표현이 불가능 한거로 알아서 미묘한 오차가 생길 줄 알았는데 예상 외 였다.

Comparable<Stage>