Groo

모의고사 본문

프로그래밍 기초/Data structure & Algorithm

모의고사

김주엽 2020. 7. 30. 09:19
반응형

안녕하세요, 오늘은 저번과 같이 코딩 테스트 연습 문제에 대한 글을 작성하려고 합니다.
이번에 소개하는 문제는 크게 어렵지 않아 저번보다 훨씬 더 빠르게 이해할 수 있을 것입니다.

📚 문제 설명

어느 날, 수포자 삼인방은 모의고사에 출제된 수학 문제를 전부 찍으려 합니다.

세 명의 수포자는 1번 문제부터 마지막 문제까지 아래와 같은 규칙으로 문제를 찍습니다.

 

1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때

가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.

 

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번 문제부터 마지막 문제까지 다음과 같이 찍습니다. 1번 수포자가 찍는 ��

programmers.co.kr

📸 제한 사항

1) 시험은 최대 10,000 문제로 구성되어있습니다.
2) 문제의 정답은 1, 2, 3, 4, 5 중 하나입니다.
3) 가장 높은 점수를 받은 사람이 여럿일 경우, return 하는 값을 오름차순으로 정렬 바랍니다.

🗣 입출력 예시

answers return
[1, 2, 3, 4, 5] [1]
[1, 3, 2, 4, 2] [1, 2, 3]

첫 번째 입출력 예시에서 수포자 1은 모든 문제를 맞혔습니다. 그러나 수포자 2, 3은 모든 문제를 틀렸습니다. 그렇기 때문에 가장 문제를 많이 맞힌 사람은 수포자 1입니다. 반면에 두 번째 입출력 예시에서는 모든 사람이 2문제씩 동일하게 문제를 맞혔습니다.

 

📨 나의 해결책 (2시간 10분 소요)

# 멤버 변수

클래스 내부에 존재하는 아래의 멤버 변수들 중 정수형 first, second, third 배열은 1번, 2번, 3번 수포자들이 수학 문제를 찍는 규칙을 나타내고 있습니다. 또한 정수형 result 배열은 각각의 수포자들이 맞춘 수학 문제의 개수를 기억하는 역할을 하고 있습니다.

int[] first = {1, 2, 3, 4, 5};
int[] second = {2, 1, 2, 3, 2, 4, 2, 5};
int[] third = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};

int[] result = {0, 0, 0};

# solution 메소드

solution 메소드는 answers 라는 정수형 배열을 인자로 전달 받고 있으며 현재 이 배열 안에는 수학 문제에 대한 답안이 들어있습니다. 또한 이 메소드에서는 각각의 함수를 호출하는 역할을 하며 최종적으로 가장 문제를 많이 맞춘 수포자의 배열을 리턴합니다.

public int[] solution(int[] answers) {
    compareData(answers);

    int[] memberList = findMember();
    return memberList;
}

# compareData 메소드

이 메소드에서는 인자로 전달받은 answers 배열 내부에 존재하는 답안과 각각의 수포자들이 찍은 답안을 비교하여 만약 옳다면 result 배열 값을 알맞게 증가시키는 역할을 하고 있습니다. 또한 여기서 주의할 점은 for 반복문 안에 존재하는 if 조건문입니다.

 

조건문의 조건을 본다면 first, second, third 배열의 인덱스 값을 5, 8, 10으로 순차적으로 나누어주고 있습니다. 이와 같은 작업을 해주는 이유는 수학 문제의 개수가 정적으로 정해져 있지 않고 10,000문제 이하로 문제가 동적으로 출제될 수 있기 때문입니다.

public void compareData(int[] answers) {
    for (int i = 0; i < answers.length; i++) {
        if (answers[i] == first[i % 5]) result[0]++;
        if (answers[i] == second[i % 8]) result[1]++;
        if (answers[i] == third[i % 10]) result[2]++;
    }
}

# findMember 메소드

findMember 메소드의 가장 큰 역할은 result 배열을 바탕으로 가장 많은 문제를 맞춘 수포자를 찾습니다. 가장 많은 문제를 맞춘 수포자는 한 명일 수도 있고, 세 명 모두 일 수도 있습니다. 또한 findMember 메소드의 반환형은 정수형 자료형의 배열입니다.

public int[] findMember() {
    int max = result[0];

    for (int i : result) {
        if(max <= i) max = i;
    }

    ArrayList<Integer> member = new ArrayList<>();

    for (int i = 0; i < result.length; i++) {
        if (max == result[i]) member.add(i + 1);
    }

    int[] memberList = new int[member.size()];

    for (int i = 0; i < memberList.length; i++) {
        memberList[i] = member.get(i);
    }

    return memberList;
 }

[ 전체 소스코드 ]

class Solution {
    
    int[] first = {1, 2, 3, 4, 5};
    int[] second = {2, 1, 2, 3, 2, 4, 2, 5};
    int[] third = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};

    int[] result = {0, 0, 0};

    public int[] solution(int[] answers) {
        compareData(answers);

        int[] memberList = findMember();
        return memberList;
    }

    public void compareData(int[] answers) {
        for (int i = 0; i < answers.length; i++) {
            if (answers[i] == first[i % 5]) result[0]++;
            if (answers[i] == second[i % 8]) result[1]++;
            if (answers[i] == third[i % 10]) result[2]++;
        }
    }

    public int[] findMember() {
        int max = result[0];

        for (int i : result) {
            if(max <= i) max = i;
        }

        ArrayList<Integer> member = new ArrayList<>();

        for (int i = 0; i < result.length; i++) {
            if (max == result[i]) member.add(i + 1);
        }

        int[] memberList = new int[member.size()];

        for (int i = 0; i < memberList.length; i++) {
            memberList[i] = member.get(i);
        }

        return memberList;
    }
}

🎨 모범 답안 (완전탐색)

이번 문제에 대한 모범 답안은 앞에서 제가 풀었던 방식과 거의 같은 형식의 로직으로 풀이가 되었습니다. 그러나 여기서 놀라웠던 점은 이번에 제가 풀었던 방식이 모범 답안보다 테스트 속도가 몇 배나 더 빨랐다는 것입니다. 아주 신기했으며 기분이 좋았습니다.

class Solution {
    
    public int[] solution(int[] answers) {
        int[] a = {1, 2, 3, 4, 5};
        int[] b = {2, 1, 2, 3, 2, 4, 2, 5};
        int[] c = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};

        int[] score = new int[3];

        for (int i = 0; i < answers.length; i++) {
            if (answers[i] == a[i % a.length]) score[0]++;
            if (answers[i] == b[i % b.length]) score[1]++;
            if (answers[i] == c[i % c.length]) score[2]++;
        }

        int maxScore = Math.max(score[0], Math.max(score[1], score[2]));

        ArrayList<Integer> list = new ArrayList<>();
        if (maxScore == score[0]) list.add(1);
        if (maxScore == score[1]) list.add(2);
        if (maxScore == score[2]) list.add(3);

        return list.stream().mapToInt(i -> i.intValue()).toArray();
    }
}

👍 글을 마치며

오늘은 모의고사라는 문제를 풀어보았습니다. 이 문제는 이전에 풀었던 문제들보다는 쉬운 문제여서 조금 더 빠르게 문제를 풀 수 있었습니다. 이번 문제에서 핵심이라고 할 수 있는 코드는 compareData 메소드 속 각 인덱스 값을 5, 8, 10으로 나누어주는 것입니다. 만약 이 과정을 코드 상에서 추가해주지 않는다면 프로그램 테스트 과정 속 시간 초과로 문제를 최종적으로 틀리게 될 것입니다.

반응형

'프로그래밍 기초 > Data structure & Algorithm' 카테고리의 다른 글

체육복  (0) 2020.08.13
집합에 대해서  (0) 2020.08.06
완주하지 못한 선수  (2) 2020.07.21
크레인 인형뽑기 게임  (2) 2020.07.15
정렬에 대해서  (0) 2020.04.02
Comments