[프로그래머스/Java] Lv.0 전국 대회 선발 고사

febCho·2024년 3월 18일
0

코딩테스트

목록 보기
102/253
post-thumbnail

문제

0번부터 n - 1번까지 n명의 학생 중 3명을 선발하는 전국 대회 선발 고사를 보았습니다. 등수가 높은 3명을 선발해야 하지만, 개인 사정으로 전국 대회에 참여하지 못하는 학생들이 있어 참여가 가능한 학생 중 등수가 높은 3명을 선발하기로 했습니다.

각 학생들의 선발 고사 등수를 담은 정수 배열 rank와 전국 대회 참여 가능 여부가 담긴 boolean 배열 attendance가 매개변수로 주어집니다. 전국 대회에 선발된 학생 번호들을 등수가 높은 순서대로 각각 a, b, c번이라고 할 때 10000 × a + 100 × b + c를 return 하는 solution 함수를 작성해 주세요.

- 제한사항

  • 3 ≤ rank의 길이 = attendance의 길이 ≤ 100
  • rank[i]는 i번 학생의 선발 고사 등수를 의미합니다.
  • rank의 원소는 1부터 n까지의 정수로 모두 서로 다릅니다.
  • attendance[i]는 i번 학생의 전국 대회 참석 가능 여부를 나타냅니다.
  • attendance[i]가 true라면 참석 가능, false면 참석 불가능을 의미합니다.
  • attendance의 원소 중 적어도 3개는 true입니다.

풀이

- 오답

코드 실행 시 테스트 케이스는 통과했는데, 제출하니까 합계가 15.8 밖에 안 되었다ㅜ
참석이 가능한 학생의 등수가 아니라 정수 배열 rank에서의 인덱스 값을 구한 다음 연산해 return하는 건데, 대체 무엇이 잘못 된 건지.. 반례를 찾을 수가 없었다.

+) 문제를 다시 풀다 보니 indexOf()가 가진 한계가 떠올랐다. 예를 들어 등수가 10 이상인 학생이 있을 때, 위 메서드를 통해 인덱스를 반환 받게 된다면 문자열 10의 인덱스가 아닌 1의 인덱스를 반환하게 되고 이에 부정확한 값이 도출될 수 밖에 없었던 거다.

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

class Solution {
    public int solution(int[] rank, boolean[] attendance) {
        List<String> rankList = new ArrayList<>();
        String rankStr = "";
        for(int i=0;i<rank.length;i++){
            rankStr += String.valueOf(rank[i]);
        }
        
        for(int i=0;i<rank.length;i++){
            if(attendance[i] == true) rankList.add(String.valueOf(rank[i]));
        }
        
        Collections.sort(rankList);
        
        int answer = (10000 * rankStr.indexOf(rankList.get(0)))
                    + (100 * rankStr.indexOf(rankList.get(1)))
                    + rankStr.indexOf(rankList.get(2));
        
        return answer;
    }
}

- 정답

이 문제는 실제 등수(rank에 저장된 값)와 인덱스(rank 배열 속 값들의 위치)라는 2가지 데이터가 존재한다. 따라서 이를 keyvalue의 관계로 보면 되겠다는 생각이 들었다. 어제 코딩 테스트를 하며 다시 한 번 익힌 Map 객체를 사용해 보기로 했다.

rank와 attendance 배열의 길이가 같으므로 둘 중 하나를 기준으로 삼고 for문으로 루프를 돈다. 이때, 참석 가능하다면(attendance[i] == true) Map 객체에 key와 value의 쌍으로 put()한다. 우리는 등수를 기준으로 인덱스 값을 연산해야 하니 key가 등수, 인덱스가 value가 된다.

루프를 돌며 attendance[i] == true인 경우, 즉 참석 가능한 경우에만 map에 값을 저장한다. 그리고 keySet() 메서드를 통해 map 객체에서 값을 꺼낸 다음 List<Integer> keyList에 넣어준다. List 객체로 옮겨 담는 이유는 Collections.sort()를 통해 등수를 오름차순으로 정렬하기 위함이다.

이후 List 객체에서 get() 메서드로 3순위까지의 값을 꺼내고, map 객체에서 get() 메서드로 key에 해당하는 value 값(인덱스)을 꺼내 연산을 해준다.

import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

class Solution {
    public int solution(int[] rank, boolean[] attendance) {
        Map<Integer, Integer> rankMap = new HashMap<>();
        for(int i=0;i<rank.length;i++){
            if(attendance[i] == true) rankMap.put(rank[i], i); 
        }
        
        List<Integer> keyList = new ArrayList<>(rankMap.keySet());
        Collections.sort(keyList);
        
        int answer = (10000 * rankMap.get(keyList.get(0)))
                    + (100 * rankMap.get(keyList.get(1)))
                    + rankMap.get(keyList.get(2));
        
        return answer;
    }
}

결과

profile
Done is better than perfect.

0개의 댓글