hoon's bLog

Java 프로그래머스 실패율 자바 본문

코딩테스트/프로그래머스

Java 프로그래머스 실패율 자바

개발한기발자 2022. 7. 1. 17:34
반응형

문제 출처 : https://programmers.co.kr/learn/courses/30/lessons/42889

 

코딩테스트 연습 - 실패율

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

programmers.co.kr


[나의 풀이]

- 스테이지 수 N만큼 반복하며, 분자/분모 만들기!

- 만든 분자/분모로 실패율을 계산하여 배열에 담아 출력

public class Solution{
    public int[] solution(int N, int[] stages) {
        int[] answer = new int[N];
        double[] failArr = new double[N];
        for (int i=0; i < N; i++) {               // 스테이지 수 N만큼 반복
            double clearCnt = 0;                //스테이지 도달한 플레이어 수 - 분모
            double ingCnt = 0;                  //스테이지 중인 플레이어 수 - 분자
            for (int j=0; j<stages.length; j++) {
                if(i+1 == stages[j]){           //i+1번째 스테이지 깻는지 체크하여 분모/분자 증가
                    ingCnt++;
                    clearCnt++;
                }else if (i+1 < stages[j]){
                    clearCnt++;
                }
            }
            if(clearCnt != 0){                  //분모가 0일때는 연산하지 않고 0값 넣기
                failArr[i] = ingCnt / clearCnt;
                answer[i] = i+1;
            }else{
                failArr[i] = 0;
                answer[i] = i+1;
            }
        }

        double tmp = 0;     //실패율 배열 값을 담을 임시 변수
        int stgTmp = 0;     //해당 스테이지 값을 담을 임시 변수

        for (int i=0; i < failArr.length; i++) {
            for (int j=i+1; j < failArr.length; j++) {
                if (failArr[i] > failArr[j]){
                    continue;
                }else if(failArr[i] == failArr[j]){
                    if(answer[i] < answer[j]){
                        continue;
                    }else{
                        stgTmp = answer[i];
                        answer[i] = answer[j];
                        answer[j] = stgTmp;
                    }
                }else{
                    tmp = failArr[i];
                    failArr[i] = failArr[j];
                    failArr[j] = tmp;
                    stgTmp = answer[i];
                    answer[i] = answer[j];
                    answer[j] = stgTmp;
                }
            }
        }
        return answer;
    }
}

 

[다른 사람의 풀이-1]

class Solution {
    public int[] solution(int N, int[] stages) {
        int[] answer = new int[N];
        double[] tempArr = new double[N];
        int arrLength = stages.length;
        int idx = arrLength;
        double tempD = 0;
        int tempI = 0;
        for (int i = 0; i < arrLength; i++) {
            int stage = stages[i];
            if (stage != N + 1)
                answer[stage - 1] += 1;
        }
        for (int i = 0; i < N; i++) {
            int personNum = answer[i];
            tempArr[i] = (double) personNum / idx;
            idx -= personNum;
            answer[i] = i + 1;
        }

        for (int i = 0; i < N; i++) {
            for (int j = 1; j < N - i; j++) {
                if (tempArr[j - 1] < tempArr[j]) {
                    tempD = tempArr[j - 1];
                    tempArr[j - 1] = tempArr[j];
                    tempArr[j] = tempD;

                    tempI = answer[j - 1];
                    answer[j - 1] = answer[j];
                    answer[j] = tempI;
                }
            }
        }
        return answer;
    }
}

[다른 사람의 풀이-2]

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Solution {
    public int[] solution(int N, int[] lastStages) {
        int nPlayers = lastStages.length;
        int[] nStagePlayers = new int[N + 2];
        //nStagePlayers 배열에 각 스테이지별 플레이어 수 저장
        for (int stage : lastStages) {
            nStagePlayers[stage] += 1;
        }

        int remainingPlayers = nPlayers;
        List<Stage> stages = new ArrayList<>();
        for (int id = 1 ; id <= N; id++) {
            double failure = (double) nStagePlayers[id] / remainingPlayers;
            remainingPlayers -= nStagePlayers[id];

            //Stage 클래스객체에 해당 stage와 실패율을 리스트에 저장
            Stage s = new Stage(id, failure);
            stages.add(s);
        }
        //내림차순으로 정렬
        Collections.sort(stages, Collections.reverseOrder());

        int[] answer = new int[N];
        for (int i = 0; i < N; i++) {
            answer[i] = stages.get(i).id;
        }
        return answer;
    }

    /**
     * 내부 클래스 : 클래스 안에 선언된 클래스
     * 클래스 안에 인스턴스 변수, 즉 필드를 선언하는 위치에 선언되는 경우. 보통 중첩클래스 혹은 인스턴스 클래스라고 한다
     * 메소드 안에 클래스를 선언한 경우, 지역 중첩 클래스 또는 지역 클래스라고 한다. 메소드 안에서 해당 클래스를 이용할 수 있다.
     */
    class Stage implements Comparable<Stage> {
        public int id;
        public double failure;

        public Stage(int id_, double failure_) {
            id = id_;
            failure = failure_;
        }

        /**
         * @Override : 자바 컴파일러에게 부모 클래스로부터 메소드 오버라이딩을 하겠다는 메시지 전달
         * 반환형, 메소드 이름, 매개 변수가 모두 같은 오버라이딩 가능한 메소드가 없다면 잘못 되었다고 알려줌.
         * 자바에서 메소드 오버라이딩이란, 상속의 관계에 있는 클래스 간에 하위 클래스가 상위 클래스와 '완전 동일한 메소드'를 덮어쓴다는 의미
         * 여기서 '완전 동일한 메소드'라는 말은 이름과 반환형이 같으면서 매개변수의 개수와 타입까지 모두 같은 메소드라는 의미
         * Comparable 클래스의 compareTo 메서드는 매개변수로 Generic변수를 받지만 @Override를 사용하여 Stage 클래스객체를 매개변수로 받아 사용
         **/
        @Override
        public int compareTo(Stage o) {
            if (failure < o.failure ) {
                return -1;
            }
            if (failure > o.failure ) {
                return 1;
            }
            return 0;
        }
    }
}

[다른 사람의 풀이-3]

import java.util.*;

class Solution {
    public int[] solution(int N, int[] stages) {
        int[] answer = {};
        int idx = 0;
        int user = stages.length;

        Map<Integer, Double> result = new HashMap<>();
        Arrays.sort(stages);

        for (int i = 1; i < N + 1; i++) {
            int cnt = 0;
            //같은 숫자라면 카운트 증가
            for (int j = idx; j < stages.length; j++) {
                if (i == stages[j]) {
                    cnt++;
                } else {
                    //아니라면 스테이지가 올라간거니깐 인덱스 저장해주고 반복 종료
                    idx = j;
                    break;
                }
            }
            if (user > 0) {
                //실패율과 인덱스를 맵에 저장
                result.put(i, ((double) cnt / (double) user));
                user -= cnt;
            } else {
                //실패율이 0일 경우 저장
                result.put(i, (double) 0);
            }

        }
        List<Integer> listKeySet = new ArrayList<>(result.keySet());

        // collections sort를 통해 value 값으로 내림차순 정렬
        Collections.sort(listKeySet, (value1, value2) -> (result.get(value2).compareTo(result.get(value1))));
        // 정렬한 리스트의 키값을 배열로 만들어서 리턴
        answer = listKeySet.stream().mapToInt(Integer::intValue).toArray();

        return answer;
    }
}

 

[정리]

- 역시나 배열과 반복문의 조화를 잘 이용하여 푸는 문제... 

- 하지만 자바가 객체지향 언어인 만큼 2번 풀이처럼 내부 클래스를 이용해 보는 방법도 나쁘지 않은 듯

 

개인 피셜 난이도 : ★☆☆

1단계에서는 주로 배열과 반복문을 얼마나 잘 활용하느냐가 관건인 것 같다.

그럼에도 불구하고 계속해서 다른 사람들의 풀이를 보는 이유는,

더 좋은 아이디어, 더 성능이 좋은 코드를 만들기 위해서다.

내가 보고도 잘 이해가 되지 않는 코드는,

내 것이 될 때까지 리뷰와 디버깅을 해보자!

 

끝.

728x90
반응형