카테고리 없음

모의고사

Dev.gunnuuu 2024. 10. 24. 14:57

https://school.programmers.co.kr/learn/courses/30/lessons/42840?language=java

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

문제 설명

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.

1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...
3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...

1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.

제한 조건
  • 시험은 최대 10,000 문제로 구성되어있습니다.
  • 문제의 정답은 1, 2, 3, 4, 5중 하나입니다.
  • 가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.
입출력 예 설명

입출력 예 #1

  • 수포자 1은 모든 문제를 맞혔습니다.
  • 수포자 2는 모든 문제를 틀렸습니다.
  • 수포자 3은 모든 문제를 틀렸습니다.

따라서 가장 문제를 많이 맞힌 사람은 수포자 1입니다.

입출력 예 #2

  • 모든 사람이 2문제씩을 맞췄습니다.

풀이

import java.util.*;

class Solution {
    public int[] solution(int[] answers) {
        // 각 사람의 답 패턴을 정의
        int[][] solution = new int[3][];
        solution[0] = new int[answers.length];
        solution[1] = new int[answers.length];
        solution[2] = new int[answers.length];
        
        // 각 패턴을 반복하여 배열을 채움
        for (int i = 0; i < answers.length; i++) {
            solution[0][i] = new int[]{1, 2, 3, 4, 5}[i % 5]; // 200번 반복 대신
            solution[1][i] = new int[]{2, 1, 2, 3, 2, 4, 2, 5}[i % 8]; // 125번 반복 대신
            solution[2][i] = new int[]{3, 3, 1, 1, 2, 2, 4, 4, 5, 5}[i % 10]; // 100번 반복 대신
        }

        // 정답 맞춘 개수
        int[] counts = new int[3];
        for (int i = 0; i < answers.length; i++) {
            if (answers[i] == solution[0][i]){
                counts[0]++;
            } 
            if (answers[i] == solution[1][i]){
                counts[1]++;
            } 
            if (answers[i] == solution[2][i]){
                counts[2]++;
            } 
        }
        
        // 가장 많이 맞춘 사람 찾기, Math.max 먼데 개편함
        int max = Math.max(counts[0], Math.max(counts[1], counts[2]));
        List<Integer> corrects = new ArrayList<>();
        for (int i = 0; i < counts.length; i++) {
            if (counts[i] == max) {
                corrects.add(i + 1); // 1번 수포자부터 시작
            }
        }

        // 결과 배열로 반환
        return corrects.stream().mapToInt(i -> i).toArray();
    }
}

각 수포자마다 패턴이 다르므로 이들을 하나의 배열에 저장해놓고 반복문을 사용하여 매개변수로 받아온 answers배열과 같은 인덱스의 값들을 비교하여 맞는 개수가 가장 많은 배열 혹은 배열들을 하나의 배열에 저장하고 출력하면 되겠다는 생각으로 구현을 시작하였다. 우선 수포자는 3명이므로 3개의 행, 문제의 개수만큼의 열로 수포자별 패턴을 담을 2차원 배열을 생성해주었다. 그 뒤 문제에서 최대 문제의 개수는 1000개 이므로 수포자의 패턴별로  for문을 사용하여 정답의 길이만큼 반복되며 맞추어 초기화 될 수 있도록 구현하여주었는데 방법으로 각  solution의 두번째[] 값은 [i % 패턴의 길이]로 하여주었는데 예시로 1번 수포자 경우는 1,2,3,4,5가 패턴이므로 패턴에서 i % 5(패턴길이) 에 해당하는 인덱스가 패턴에서 1,2,3,4,5  다시 1부터 2,3,4,5 순으로 i가 계속 증가하여도 패턴을 돌며 패턴의 길이별로 초기화 해주도록 각각 구현해 주었다. 다음으로 수포자의 패턴별로 각 정답을 맞춘 개수를 구해주었다. 우선 3명의 수포자별 맞춘 개수를 저장할 배열 counts를 생성해준 뒤,  for문을 사용하여  solution[][] 의 첫번째 []  즉, 행 인덱스별로(각 수포자별 패턴) 각각  i 번째 인덱스의 값끼리 비교하여 같으면 해당 패턴을 사용하여 찍은 값이 맞았으므로 counts에 해당 행 인덱스의 값을 ++ 해주어  맞춘 개수들을 저장해주었다. 마지막으로는 가장 많이 맞춘 수포자를 결과 배열로 출력해주어야 하였는데 이를위해 max변수를 따로 만들어 반복문으로 비교하여 저장하려했지만 오류나 시간초과도 뜨고 좀더 간단한 방법이 없을까 하여 구글링 하다 Math.max 메소드를 찾았다. 이를 사용하여 편하게 가장 맞춘 개수를 구하여 초기화 한 뒤에 for문을 사용하여 counts와 max를 비교하여 가장 많이 맞춘 사람(복수명 가능)을 찾아 corrects 리스트에 저장하여 주었다. 그 뒤 문제에서는 배열로 리턴하주길 원하였으므로 리스트에서 배열로 변환을 해주어야했다.  int[] aarr = corrects.toArray(new int[corrects.size()]); 처럼 toArray메소드를 사용하여 처음에는 구현해주었는데 이 메소드는 object타입을 리턴하므로 참조타입인 String 타입은 호환이되어 가능하지만 int 타입일 경우에는 직접 변환하려면 오류가 발생하여 사용이 불가능한걸 알게 되었다. 그러므로 mapToInt메소드를 사용하여 int형으로 변환하여 준뒤에 toArray메소드를 사용하여 배열로 변환해준 뒤 리턴하는 방법으로는 오류없이 잘 구현할수 있었다.