본문 바로가기

Algorithm (Java)/문제풀이

[자바/Java] 프로그래머스 - 모의고사 (Level1- 브루트포스)

[자바/Java] 프로그래머스 - 모의고사 (level1- 브루트포스)

https://school.programmers.co.kr/learn/courses/30/lessons/42840

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

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하는 값을 오름차순 정렬해주세요.

 

입출력 예
answers return
[1,2,3,4,5] [1]
[1,3,2,4,2] [1,2,3]
입출력 예 설명

입출력 예 #1

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

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

입출력 예 #2

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

 

 

문제풀이

1. 수포자 1, 2, 3의 찍기패턴[?]을 int형 배열 ptn1, ptn2, ptn3에 각각 담음

2. 수포자 1, 2, 3이 맞춘 갯수를 cnt[1], cnt[2], cnt[3]에 순서대로 담는 int[4] 형 배열 cnt 선언 

3. 수포자의 답과 정답이 일치하는 경우, cnt의 해당 인덱스를 1 증가

  로직1: 

  • 수포자 1의 경우, 5개를 기준으로 나의 답이 반복되므로 ptn1[a]의 값은 ptn1[a%5]의 값과 같다.
  • 수포자 2의 경우, 8개를 기준으로 나의 답이 반복되므로 ptn2[a]의 값은 ptn2[a%8]의 값과 같다.
  • 수포자 2의 경우, 10개를 기준으로 나의 답이 반복되므로 ptn3[a]의 값은 ptn3[a%10]의 값과 같다.

 로직2:

  • 수포자1의 답이 정답과 일치하는 case : answer[i] = ptn1[i%5]  -> cnt[1]++
  • 수포자 2의 답이 정답과 일치하는 case :  answer[i] = ptn1[i%8]  -> cnt[2]++
  • 수포자 3의 답이 정답과 일치하는 case :  answer[i] = ptn1[i%10]  -> cnt[3]++

4. Math.max()메소드를 이중으로 사용하여 cnt배열 중 최댓값을 찾은 후, int max에 저장

5.  가장 많은 문제를 맞힌 사람은 1명~3명까지 가능하므로, 가변길이 저장이 가능한 ArrayList<Integer> result 선언

6.  1=<i<4만큼 반복문을 돌면서, 저장해둔 최댓값과 cnt[i]가 일치한다면, result에 add

7.  최종적으로 최댓값 가지는 수포자(들) 반환하는 배열을 return 하기 위해, ArrayList형 result를 int형배열로 변환작업 진행

 

 

구현코드

import java.lang.*;
import java.util.*;

class Solution {
    public int[] solution(int[] answers) {
        int[] ptn1 = {1, 2, 3, 4, 5};
        int[] ptn2 = {2, 1, 2, 3, 2, 4, 2, 5};
        int[] ptn3 = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
    

        int[] cnt = {0,0,0,0};
        
        for(int i=0; i< answers.length; i++){
           if(answers[i] == ptn1[i%5]) cnt[1]++;
           if(answers[i] == ptn2[i%8]) cnt[2]++;
           if(answers[i] == ptn3[i%10]) cnt[3]++;                                
        }
        
        int max= Math.max(Math.max(cnt[1], cnt[2]),cnt[3]);
        ArrayList<Integer> result = new ArrayList<Integer>();
        for(int i=1; i<4; i++){
            if(max==cnt[i]) result.add(i);
        }
        
        
        int[] resultToArr = new int[result.size()];
        for(int i=0; i<result.size(); i++){
            resultToArr[i] = result.get(i);            
        }
        
        return resultToArr;
    }
}

 소회 

  1.  처음 문제를 보자마자 쉽다고 생각했으나,  알고리즘이 익숙하지 않은 내 머릿속에는 가장 비효율(ㅠㅠ)적으로 푸는 방법만 떠오름 : 수포자1, 2, 3의 answers.length만큼의 답을 모두 채운 배열을 만들고, 각 배열의 모든 인덱스를 돌며 answers[i]와 일치하는지 모두 비교하는 방법
  2. 다른 풀이법을 보자마자 '이래서 알고리즘을 공부하는구나' 또다시 생각...
  3. 특정규칙이 반복되는 배열의 값과 다른 배열을 비교할 때에는, 최소규칙을 담은 배열arr을 두고 i%arr.length 와 비교배 열 인덱스를 비교하면 된다는 점이 중요한 포인트였다.
  4. 최댓값을 가지는 수포자가 1~3명까지 가능하므로, 최종결과를 담은 배열을 return하기 전, 크기변경이 가능한 arraylist에 값을 담고, 해당 arraylist크기만큼 다시 int형 배열을 선언하고, 값을 채운 후 return하는 부분을 통해, 배열과 ArrayList을 어떤 상황에 어떻게 코드로 적용해야하는지 체감할 수 있어 좋았다.