[프로그래머스] 모의고사(자바)

지수·2021년 8월 4일
0
post-thumbnail

알고리즘 문제 풀이를 블로그에 올리는 이유는 풀이, 코드를 기록하기 위함이니
앞으로 문제를 다 긁어오기보다 링크만 두고 풀이가 잘 보이도록 포스팅 할 예정입니다!

📄 문제

[프로그래머스] 모의고사


👩‍💻 풀이

1. 문제 이해

이 문제는 수포자 세 명의 답안 리스트와 정답 리스트를 하나씩 비교해가며 채점 후
가장 점수가 높은 수 포자를 구하는 문제이다.

2. 첫번째 풀이(비추🔥)

  • Student class를 만들어 수포자 번호, 답안(찍는 패턴), 점수(채점 결과)를 멤버 변수로 선언
  • 수포자별 답안(찍는 패턴)을 각각 ans1, ans2, ans3 배열에 할당
  • 수포자 번호, 답안(ans1, ans2, ans3), 점수(0으로 초기화)를 넣어 Student 객체 생성
  • Student 객체를 students LinkedList에 할당
  • 정답 리스트 길이만큼 반복문을 돌고, 안에 for each문으로 Student 인스턴스를 하나씩 뽑아 답안과 비교 = 채점
  • Math.max를 활용하여 최대 점수 계산
  • for each문으로 Student 인스턴스를 하나씩 뽑아 점수가 최고점수(topScore)와 같은 수포자의 번호를 winner 리스트에 add
  • winner 리스트를 answer로 옮겨 return
import java.util.LinkedList;

public class Solution {

    static class Student{
        int studentNo;
        int[] answerlist;
        int score;

        Student(int studenNo, int[] answerlist, int score) {
            this.studentNo = studenNo;
            this.answerlist = answerlist;
            this.score = score;
        }
    }

    public static int[] solution(int[] answers) {
        int[] ans1 = {1, 2, 3, 4, 5};
        int[] ans2 = {2, 1, 2, 3, 2, 4, 2, 5};
        int[] ans3 = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};

        Student student1 = new Student(1, ans1, 0);
        Student student2 = new Student(2, ans2, 0);
        Student student3 = new Student(3, ans3, 0);

        LinkedList<Student> students = new LinkedList<>();
        students.add(student1);
        students.add(student2);
        students.add(student3);

        for(int i = 0; i < answers.length; i++) {
            for(Student student : students) {
                if(answers[i] == student.answerlist[i % student.answerlist.length]) {
                    student.score++;
                }
            }
        }

        int topScore;
        int trial = Math.max(students.get(0).score, students.get(1).score);
        topScore = Math.max(trial, students.get(2).score);

        LinkedList<Integer> winner = new LinkedList<>();
        for(Student s : students) {
            if(s.score == topScore) {
                winner.add(s.studentNo);
            }
        }

        int[] answer = new int[winner.size()];
        for(int i = 0; i < answer.length; i++) {
            answer[i] = winner.get(i);
        }
        return answer;
    }
}

수업에서 유지보수가 용이하도록, 가독성이 높도록 코드 짜는 연습을 하다보니
클래스를 만드는 것에 꽂혀버린 것 같다..ㅎㅎ;;

이 문제에서는 굳이 Student 객체를 생성하거나 students 리스트에 인스턴스를 넣는 등의 과정이 크게 필요하지 않을 것 같다.
괜히 객체를 추가로 생성해서 불필요한 메모리도 많이 차지하고, 반복문을 사용하여 객체 안의 값을 또 탐색하는 과정이 속도도 늦추는 것 같다.
위의 코드는..(열심히 짠 코드지만 또로록😢) 비추한다!

+) 프로그래머스 채점 점수는 높았는데, 그 점수가 의미하는 바가 무엇인지 아직 잘 모르겠다..?


3. 개선한 풀이

  • 따로 클래스를 생성하지 않고, 반복문과 if문만 활용하여 값 비교 및 채점 결과(점수) 할당
  • +) 이전 코드에서는 다 LinkedList를 썼는데, 굳이 LinkedList일 필요가 없어서 winner를 ArrayList로 선언
  • +) 기존에 for each문을 사용하여 List를 배열로 바꿔주는 부분을 int[] answer = winner.stream().mapToInt(i -> i).toArray();로 변경!
import java.util.ArrayList;

public class Solution {

    public static int[] solution(int[] answers) {
        int[] ans1 = {1, 2, 3, 4, 5};
        int[] ans2 = {2, 1, 2, 3, 2, 4, 2, 5};
        int[] ans3 = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};

        int score1 = 0;
        int score2 = 0;
        int score3 = 0;

        for(int i = 0; i < answers.length; i++) {
            if(answers[i] == ans1[i % ans1.length]) {score1++;}
            if(answers[i] == ans2[i % ans2.length]) {score2++;}
            if(answers[i] == ans3[i % ans3.length]) {score3++;}
        }

        int topScore = Math.max(Math.max(score1, score2), score3);

        ArrayList<Integer> winner = new ArrayList<>();
        if(score1 == topScore) {winner.add(1);}
        if(score2 == topScore) {winner.add(2);}
        if(score3 == topScore) {winner.add(3);}

        int size = winner.size();
        int[] answer = winner.stream().mapToInt(Integer::intValue).toArray();

        return answer;
    }
}

이 풀이의 백미는 아무래도 마지막 int[] answer = winner.stream().mapToInt(i -> i).toArray(); 부분이다!
값을 인덱스 없이 넣어주어야 할 때마다 리스트 자료구조를 써야하는데,
최종적으로 이를 다시 배열에 넣어주는 과정에서 반복문을 쓰는 부분이 너무 거슬렸다.

드디어 찾은 ArrayList / LinkedList => arry[] 방법
: stream, mapToInt, toArray() 사용
출처: [java] 정수를 포함하는 ArrayList를 기본 int 배열로 변환하는 방법은 무엇입니까?


4. 스터디원분들과 최적화 🌱

외로운 자바 공부에 날개를 달기 위해..!ㅋㅋ
같이 자바로 코딩 테스트 문제를 풀고 서로의 풀이를 공유하는 스터디를 만들었다..!
기존에 참여중이던 코딩 테스트 스터디도 좋지만, 해당 스터디에서는 나 혼자 자바를 쓰기에ㅠㅠ
더 많은 자바 코드를 보고 싶어서 🧡플레이데이터 자바 코테 스터디🧡를 만들었다.

✅ 스터디 진행 방식
1. 매주 정해진 양의 문제를 각자 풀고, 구글 드라이브에 코드와 코드 요약 설명을 공유한다.
2. 매주 수요일 줌에서 스터디 진행!
3. 문제별로 랜덤 1명을 뽑아 자신의 코드를 발표하고, 스터디원 다같이 발표자의 코드를 최적화한다.

스터디를 루즈하지 않게 운영하고 싶어서 고민이 많았는데, 플레이데이터 매니저님이 위 방법을 추천해주셨다.
서로 코드를 이해하기도 좋고, 각자 '왜 이렇게 풀었을까?'를 생각할 수 있는 시간을 가질 수 있어 유익했다! (너무 기뻐서 사담이 길었다 큼큼..)

import java.util.ArrayList;

public class Solution {

	public static int[] solution(int[] answers) {
		
		int[][] supoza = {{1,2,3,4,5}, {2,1,2,3,2,4,2,5}, {3,3,1,1,2,2,4,4,5,5}};

		int[] cnt = new int[3];
		for(int i = 0; i < cnt.length; i++) {
			for(int j = 0; j < answers.length; j++) {
				if(supoza[i][j%supoza[i].length] == answers[j]) {
					cnt[i]++;
				}
			}
		}
		
		int max = Math.max(cnt[0], Math.max(cnt[1], cnt[2]));
		
		ArrayList<Integer> list = new ArrayList<Integer>();
		for(int i = 0; i < cnt.length; i++) {
			if(max == cnt[i]) {
				list.add(i + 1);
			}
		}
		
		int[] answer = list.stream().mapToInt(Integer::intValue).toArray(); 
        
		return answer;
	}
}
profile
사부작 사부작

0개의 댓글