[260604]알고리즘 연습 1일차

이상민·2026년 6월 4일

Spring

목록 보기
18/59

목차

오늘은 알고리즘 공부를 하며, 코딩문제를 풀어보는 시간을 가져보았다.


문제설명

음악 테스트 응시자의 패턴
3명의 음악 테스트 응시자들이 음계 맞추기 시험을 봅니다. 각 응시자들은 자신만의 패턴으로 답을 찍어서 문제를 풀기로 했습니다. 이번 시험에서 누가 가장 많은 문제를 맞혔는지 알아보려 합니다.

응시자 3명의 찍기 패턴

(1) 1번 응시자의 패턴: [도, 레, 미, 파]
    * 4개의 음계를 순차적으로 반복
    * ex) 도,레,미,파,도,레,미,파,도,레,...

(2) 2번 응시자의 패턴: [레, 레, 파, 파, 도, 도]
    * 6개의 음계를 순차적으로 반복
    * ex) 레,레,파,파,도,도,레,레,파,파,...

(3) 3번 응시자의 패턴: [미, 파, 미, 도, 레, 도]
    * 6개의 음계를 순차적으로 반복
    * ex) 미,파,미,도,레,도,미,파,미,도,...

시험문제의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지를 배열에 담아 return 하는 함수를 작성해주세요.



다음과 같이 내가 정답을 입력해주면 학생 1, 2, 3번중 누가 제일 많이 맞았는지를 구별하는 문제이다.

입출력예시

입력 형식 및 예시

  • 첫째 줄: 시험 문제의 개수 N (1 ≤ N ≤ 5,000)
  • 둘째 줄: N개의 정답 문자열이 공백으로 구분되어 주어짐 (각 문자열은 "도", "레", "미", "파" 중 하나)
    JavaScript
// 예시 1
6
도 레 미 파 도 레

// 예시 2
6
미 레 도 레 도 미

이처럼 처음 scanner로 받는 값은 정답의 길이, 두번째로 받는 값은 정답의 내용을 의미한다.

//1. 클래스 이름은 반드시 Solution으로 해야 합니다.
//2. 메서드 이름은 반드시 solution으로 해야 합니다.
//3. 메서드 파라미터와 리턴 타입을 문제에서 제시한 대로 정확히 맞춰야 합니다.
//4. 아래 코드 참고

public class Solution {
    public int[] solution(String[] answers) {
     
        int[] answer = {} ;      
        return answer;   
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Solution solution = new Solution();

        // 문제 개수 입력
        int N = sc.nextInt();

        // 정답 배열 입력
        String[] answers = new String[N];
        for(int i = 0; i < N; i++) {
            answers[i] = sc.next();
        }

        // 결과 출력
        int[] result = solution.solution(answers);
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < result.length; i++) {
            sb.append(result[i]);
            if(i < result.length - 1) {
                sb.append(" ");
            }
        }
        System.out.println(sb.toString());
    }

주어진 코드를 바탕으로 solution 메서드를 완성시키는것이 이번 문제의 목표이다.

구현코드

public int[] solution(String[] answers) {

        String[] A = {"도", "레", "미", "파"};
        String[] B = {"레", "레", "파", "파", "도", "도"};
        String[] C = {"미", "파", "미", "도", "레", "도"};
        int[] score = {0, 0, 0};
        int answer_size = 0;
        //점수 계산 식

        for (int i = 0; i < answers.length; i++){
            if(A[i%4].equals(answers[i])){
                score[0]++;
            }
            if(B[i%6].equals(answers[i])){
                score[1]++;
            }
            if(C[i%6].equals(answers[i])){
                score[2]++;
            }
        }

        int[] student_num = new int[3];
        int high_score = 0;

        for (int i = 0; i < 3; i++){
            if(score[i] > high_score){
                high_score = score[i];
            }
        }
        for (int j = 0; j < 3; j++) {
            if (high_score == score[j]) {
                student_num[j] = j + 1;
                answer_size++;
            }
        }

        int[] answer = new int[answer_size];
        answer_size = 0;
        for (int j = 0; j < 3; j++){
            if(student_num[j] != 0){
               answer[answer_size] = student_num[j];
               answer_size++;
            }
        }

        return answer;
    }

이 문제를 해결하기 위하여 다음과 같이 단계를 분할했다.

1. 학생 1, 2, 3번이 정답을 반복해서 찍는것을 구현하기
2. 각 학생이 몇개의 정답을 맞췄는지 기록하기
3. 제일 많이 맞은 학생이 누군지 계산하기
4. 제일 많이 맞은 학생을 answer값에 담아서 리턴하기

1번의 경우엔 String[] A = {"도", "레", "미", "파"} 과 같은 스트링배열을 선언하고,
for문을 사용할때 A[i%4]를 통하여 계속 0~3번째 배열을 반복해서 순환하도록 만들어 주었다.


2번은 int[] score = {0, 0, 0}을 생성하여 각자 학생이 맞을때마다 score[학생번호]++을 해주는 식으로 구현하였다.


3번은

        int[] student_num = new int[3];
        int high_score = 0;

        for (int i = 0; i < 3; i++){
            if(score[i] > high_score){
                high_score = score[i];
            }
        }
        for (int j = 0; j < 3; j++) {
            if (high_score == score[j]) {
                student_num[j] = j + 1;
                answer_size++;
            }
        }

위의 코드를 구현하여, 첫번째 for문에서는 제일 많이 맞춘 학생을 구하고, 제일 많이 맞춘 정답이 중복이 될 수 있으므로 몇명의 학생이 제일 많이 맞췄는지에 대해 그 수를 구하였다.


마지막으로 4번은,
        int[] answer = new int[answer_size];
        answer_size = 0;
        for (int j = 0; j < 3; j++){
            if(student_num[j] != 0){
               answer[answer_size] = student_num[j];
               answer_size++;
            }
        }

위에서 구하였던 answer_size(많이 맞춘 학생수)를 토대로 int[] answer을 선언하고, 0이 아닌 student_num(정답일 경우 1 아니면 0)을 조건문으로 사용하여 정답일 경우에만 answer배열 안에 추가되도록 코드를 구현하였다.

테스트케이스

입력 테스트 케이스

// 테스트 케이스 1
6
도 레 미 파 도 레

// 테스트 케이스 2
6
미 레 도 레 도 미

// 테스트 케이스 3
10
레 레 파 파 도 도 레 레 파 파

// 테스트 케이스 4
12
미 파 미 도 레 도 미 파 미 도 레 도

// 테스트 케이스 5
6
도 레 미 파 도 레

테스트 케이스 결과

// 테스트 케이스 1
1

// 테스트 케이스 2
1 2

// 테스트 케이스 3
2

// 테스트 케이스 4
3

// 테스트 케이스 5
1

테스트 케이스는 다음과 같고, 실제로 잘 구현하는것을 확인하였다.

트러블슈팅

코드를 작성하면서 어려웠거나 문제가 생겼던 부분은 다음과 같다.

1. String을 비교할때 `==`연산자를 사용했는데, 그 당시에 문제가 있음을 
   알았지만 `equals`가 생각나지 않아 구글에 검색했었다.

2. for문과 쓸모없는 변수나 잠깐 거쳐가는 값이 너무 많은것 같아서 줄여보려다가 실패하였다.

3. 학생이 찍은 정답을 A[i%4]로 작성해야하는데, A[i/4]로 작성해버려서 
   오류는 나지 않았지만, 값이 이상하게 출력되었다.
  

코드를 작성하고 보면 당연한 것들이 그 당시엔 생각나지 않았다는 점에서 아직 기초를 더 확실하게 쌓아야 겠다는 생각을 갖게 되었다.
또한, 알고리즘에 관한 학습을 더 진행한 후 코드를 다시 작성하여 간결화 시켜볼 예정이다.

profile
백앤드 개발 브이로그

0개의 댓글