[프로그래머스] 코딩 테스트 입문 - 실패율(Java)

수경·2022년 11월 17일
0

problem solving

목록 보기
60/174

프로그래머스 - 실패율

문제

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

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

실패율은 다음과 같이 정의한다.
스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수
전체 스테이지의 개수 N, 게임을 이용하는 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열 stages가 매개변수로 주어질 때, 실패율이 높은 스테이지부터 내림차순으로 스테이지의 번호가 담겨있는 배열을 return 하도록 solution 함수를 완성하라.

❗️제한사항

  • 스테이지의 개수 N은 1 이상 500 이하의 자연수이다.
  • stages의 길이는 1 이상 200,000 이하이다.
  • stages에는 1 이상 N + 1 이하의 자연수가 담겨있다.
    • 각 자연수는 사용자가 현재 도전 중인 스테이지의 번호를 나타낸다.
    • 단, N + 1 은 마지막 스테이지(N 번째 스테이지) 까지 클리어 한 사용자를 나타낸다.
  • 만약 실패율이 같은 스테이지가 있다면 작은 번호의 스테이지가 먼저 오도록 하면 된다.
  • 스테이지에 도달한 유저가 없는 경우 해당 스테이지의 실패율은 0 으로 정의한다.

입출력 예시

Nstagesresult
5[2, 1, 2, 6, 2, 4, 3, 3][3,4,2,1,5]
4[4,4,4,4,4][4,1,2,3]

풀이

  1. 각 스테이지 마다의 실패율을 계산하고, 실패율을 기준으로 내림차순 정렬을 해서 스테이지를 반환해야 함
    ➡️ HashMap 타입으로 저장
    ➡️ key: 스테이지 번호
    ➡️ value: 실패율 = (스테이지에 머무르고 있는 사람의 수 / 스테이지에 도전한 사람의 수)

  2. value 값 계산 ➡️ stream().filter()를 사용

    1. 스테이지에 머무르고 있는 사람의 수
      ✔️ 해당 스테이지 번호의 요소 count

    2. 스테이지에 도전한 사람의 수
      ✔️ 해당 스테이지 번호보다 크거나 같은 요소 count

  3. value 값 기준 내림차순 정렬

  4. key 값을 요소로 하는 배열 만들어서 반환


삽질

map을 value기준으로 정렬? 오케이.. 할 수 있어 오케이...는 fail....
문제가 실패율 구하긴데 내 문제풀이 실패율 구하는게 더 빠를 뻔 했다 ㅋ...(아니 더 빨랐다)

가장 큰 문제는 두 개였다.

  1. value를 뽑아서 정렬 -> key 값을 가져와서 연결할 수 없음 -> ??? 도대체 어캐해야될까 ;;
  2. 내.림.차.순.정.렬.

🥹 하아아ㅏㅏ....

결국 이것저것 시도해보다가 검색을 하기로 했다. 어떻게든 내장함수 쓰고싶으니까악.....

랜선 선생님의 코드를 참고했다..🥹 감사합니다 선생님...

정렬 방법은 여러가지가 있지만! 일단 map에서 value기준 내림차순 정렬을 해야한다고 하면!
map자체를 요리조리 할 생각은 버려라!!!!!! (이제 생각해보니까 map은 순서가 없다... key 순서를 바꿀라고 했는데 🫠)

❗️❗️map.keySet()을 가져와서 List<> keySetList에 저장한 다음, 이 keySetList를 정렬해야 한다❗️❗️

👀 : 뭐야 그러면 value로 정렬을 어캐해?

❗️❗️정렬 시 Collections.sort()함수를 쓸 건데, 인자값에 넣어줄 때 map.get(key)로 넣어주면 된다악❗️❗️

👀: ??????

Collections.sort(List list, Comparator<? super T> c)
List<T> list : 정렬할 리스트
Comparator<? super T> c : 정렬 기준 -> 반환값에 따라 오름차순 / 내림차순 정렬을 함

// 오름차순, comparator의 반환값 : 1
Collections.sort(keySetList, (k1, k2) -> (map.get(k1).compareTo(map.get(k2))));
// 내림차순, comparator의 반환값 : -1
Collections.sort(keySetList, (k1, k2) -> (map.get(k2).compareTo(map.get(k1))));

복잡한 듯 싶지만 어찌어찌 해결!
C에서도 비슷한 코드를 봤던 경험이 있어서 금방 이해한 것 같다.
근데 설명을 못하겠어서 좀 더 명확한 공부가 필요할 것 같다!


코드

import java.util.*;

public class FailureRate {
    public int[] solution(int N, int[] stages) {
        HashMap<Integer, Double> map = new HashMap<>();
        for (int i = 0; i < N; i++) {
            int key = i + 1;
            long total = Arrays.stream(stages).filter(v -> v >= key).count();
            long fail = Arrays.stream(stages).filter(v -> v == key).count();
            map.put(key, total == 0 ? 0 : (double)fail/total);      // 스테이지에 도전한 사람이 없는 경우 실패율 0
        }

        List<Integer> keySetList = new ArrayList<>(map.keySet());
        Collections.sort(keySetList, (k1, k2) -> (map.get(k2).compareTo(map.get(k1)))); // 내림차순 정렬
        return keySetList.stream().mapToInt(k -> k).toArray();
    }

    public static void main(String[] args) {
        FailureRate failureRate = new FailureRate();
        Arrays.stream(failureRate.solution(5, new int[]{2, 1, 2, 6, 2, 4, 3, 3}))   // [3, 4, 2, 1, 5,]
                .forEach(a -> System.out.print(a + " "));
        System.out.println();
        Arrays.stream(failureRate.solution(4, new int[]{4, 4, 4, 4, 4}))            // [4, 1, 2, 3]
                .forEach(a -> System.out.print(a + " "));
        System.out.println();
        Arrays.stream(failureRate.solution(5, new int[]{3, 3, 3}))                  // [3, 1, 2, 4 ,5]
                .forEach(a -> System.out.print(a + " "));

    }
}
profile
어쩌다보니 tmi뿐인 블로그😎

0개의 댓글