| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- Lv.0
- LV02
- 코테
- SQL
- 프로그래머스
- nginx
- JPA
- CI/CD
- 데이터 베이스
- LV01
- 디자인 패턴
- 포트폴리오
- Redis
- CoffiesVol.02
- 이것이 자바다
- spring boot
- mysql
- docker
- Java
- AWS
- 연습문제
- Join
- LV03
- JMeter
- LV0
- 알고리즘
- Kafka
- 일정관리프로젝트
- 일정관리 프로젝트
- LV.02
- Today
- Total
코드 저장소.
프로그래머스- 모의고사 본문
목차
1.문제
2.문제 해결 과정
3.타인의 코드 분석
1.문제


2.문제 해결 과정
2-1.문제 요구사항
이 문제의 묻는 내용은 아래와 같습니다.
- 문제의 정답은 1,2,3,4,5 만으로 구성되어 있다.
- answers의 길이는 1이상 10000이하의 값
- 가장 높은 점수를 받은 사람이 여러 명일 경우, 오름차순으로 정렬하여 반환
2-2.문제 풀이
우선은 이 문제를 해결하기 위한 접근 방식으로는 다음과 같습니다.
1.수포자3인방의 문제를 찍는 패턴을 분석하기
수포자3인방의 경우에는 특정한 규칙을 가지고 답을 찍습니다. 아래는 수포자들의 답 찍는 방식입니다.
- 수포자1: 1,2,3,4,5.....
- 수포자2: 2,1,2,3,2,4,2,5......
- 수포자3: 3,3,1,1,2,2,4,4,5,5.....
2.수포자 3명의 답을 정답지와 비교를 하면서 대조를 하고 맞으면 점수를 세기
다음으로는 정답지를 반복문으로 돌리면서 각 수포자들의 정답 패턴을 분석을 하고 맞는 경우에는 각 학생들의 점수를 올립니다.
다만 문제를 풀면서 해당 학생들의 답을 찍는 패턴을 대조를 해봐야 하는데 문득 떠오른 것이 정답배열의 길이는 수포자 패턴의 길이보다 훨씬 길텐데 어떻게 비교를 하지? 라는 생각이 들었고 이 부분을 해결을 하기 위해서 각 수포자들의 패턴이 반복이 되니깐 배열의 길이만큼을 나머지 연산을 써서 인덱스가 순환을 하게끔 하면 되겠구나를 생각을 했습니다.
3.각 학생들의 점수를 비교후 정렬하기.
마지막으로 각 학생들의 스코어를 가지고 이중에서 제일 큰 수를 정하고 만약에 점수가 높은 사람이 2명 이상인 경우에는 오름차순으로 정렬을 하고 배열을 리턴을 하면 됩니다.
2-3.문제 의사코드
위의 사고 과정을 토대로 해서 만든 제 의사 코드입니다.
1.변수 초기화
- 각 학생들의 점수찍기패턴의 배열을 선언
- 각 학생들의 맞춘 점수 변수(score1,2,3) 선언
- 학생들 중의 최대점수를 담을 변수를 선언
- 마지막에 각 학생들의 점수를 토대로 순위를 잡을 리스트 List<Integer> 를 선언
2.정답지 배열의 길이만큼 반복문을 돌리고 반복문 안에서 각 학생들의 정답패턴과 비교
- 이때 학생들의 배열에서 나머지 연산(%)을 사용해서 인덱스를 순환하면서 비교하고 맞으면 score를 증가
3.각 학생들의 score를 비교를 해서 최댓값을 찾기
- Math.max를 사용해서 학생들의 최대값을 찾기
4.리스트를 사용해서 각 학생들의 개별점수와 최대 점수를 비교를 해서
점수가 같으면 리스트에 학생의 번호로 담기( ex: 학생1이면 1을 2면 2를 3이면 3)
5.마지막으로 리스트 타입을 배열 타입으로 전환을 하고 리턴
다음의 의사코드를 토대로 해서 작성을 한 코드는 아래와 같습니다.
import java.util.*;
class Solution {
public int[] solution(int[] answers) {
int[] answer = {};
int[] student1 = {1, 2, 3, 4, 5};
int[] student2 = {2, 1, 2, 3, 2, 4, 2, 5};
int[] student3 = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
int score1 = 0;
int score2 = 0;
int score3 = 0;
int maxScore = 0;
List<Integer>list = new ArrayList<>();
for(int i = 0; i<answers.length; i++) {
if(answers[i] == student1[i%student1.length]) {
score1 ++;
}
if(answers[i] == student2[i%student2.length]) {
score2 ++;
}
if(answers[i] == student3[i%student3.length]) {
score3 ++;
}
}
maxScore = Math.max(score1,Math.max(score2,score3));
if(score1 == maxScore) {
list.add(1);
}
if( score2 == maxScore) {
list.add(2);
}
if(score3 == maxScore){
list.add(3);
}
answer = list.stream().mapToInt(Integer::intValue).toArray();
return answer;
}
}
제가 작성한 코드를 설명을 하면 다음과 같습니다.
정답지 배열을 돌리면서 각 수포자들의 배열을 비교를 할때 나머지 연산을 활용해서 i % student1.length를 통해 10,000개의 긴 정답 배열 속에서도 5개짜리 패턴이 에러 없이 무한히 순환하며 비교될 수 있도록 구현을 했고
최대 10000번의 반복문으로 전체 경우의 수를 모두 탐색을 해야 되므로 성능의 저하 없이 안정적으로 동작한다는 점입니다.
3.타인의 코드 분석
마지막으로 문제를 맞추고 다른 사람들이 제출한 코드를 봤습니다. 제출한 코드들은 대부분의 패턴은 대동소이했습니다. 그 중에서도 눈에 띄었던 것은 객체지향적으로 짜는 코드와 map을 활용해서 점수를 관리를 한 코드였습니다.
3-1.객체지향으로 짠 코드
import java.util.*;
import java.util.function.IntPredicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Solution {
public int[] solution(int[] answers) {
return new Students().getBestStudents(
Arrays.stream(answers)
.boxed()
.map(Answer::new)
.collect(Collectors.toList()))
.stream()
.mapToInt(i -> i)
.toArray();
}
private static class Students {
private final List<Student> students;
public Students() {
this.students = new ArrayList<>();
this.students.add(Student.of(1, Arrays.asList(1, 2, 3, 4, 5)));
this.students.add(Student.of(2, Arrays.asList(2, 1, 2, 3, 2, 4, 2, 5)));
this.students.add(Student.of(3, Arrays.asList(3, 3, 1, 1, 2, 2, 4, 4, 5, 5)));
}
public List<Integer> getBestStudents(List<Answer> answers) {
return this.students.stream()
.map(student -> student.getResult(answers))
.collect(Collectors.collectingAndThen(Collectors.toList(), Results::new))
.getBestResults().stream()
.map(Result::getStudentId)
.collect(Collectors.toList());
}
}
private static class Student {
private final Integer id;
private final List<Answer> answerPattern;
public Student(Integer id, List<Answer> answerPattern) {
this.id = id;
this.answerPattern = answerPattern;
}
public static Student of(Integer id, List<Integer> answerPattern) {
return new Student(id, answerPattern.stream()
.map(Answer::new)
.collect(Collectors.toList()));
}
public Result getResult(List<Answer> answers) {
Long correctCount = IntStream.range(0, answers.size())
.filter(isCorrect(answers))
.count();
return new Result(this.id, correctCount.intValue());
}
private IntPredicate isCorrect(List<Answer> answers) {
return index -> {
int patternIndex = index % answerPattern.size();
Answer answer = answerPattern.get(patternIndex);
Answer correctAnswer = answers.get(index);
return answer.isCorrect(correctAnswer);
};
}
}
private static class Results {
private final List<Result> results;
public Results(List<Result> results) {
this.results = results;
}
public List<Result> getBestResults() {
Result bestResult = Collections.max(results);
return results.stream()
.filter(result -> result.isCorrectCountEqualTo(bestResult))
.collect(Collectors.toList());
}
}
private static class Result implements Comparable<Result> {
private final Integer studentId;
private final Integer correctCount;
public Result(Integer studentId, Integer correctCount) {
this.studentId = studentId;
this.correctCount = correctCount;
}
public boolean isCorrectCountEqualTo(Result result) {
return this.correctCount.equals(result.correctCount);
}
public Integer getStudentId() {
return studentId;
}
@Override
public int compareTo(Result o) {
return this.correctCount.compareTo(o.correctCount);
}
}
private static class Answer {
private final Integer answer;
public Answer(Integer answer) {
this.answer = answer;
}
public boolean isCorrect(Answer answer) {
return this.answer.equals(answer.answer);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Answer answer1 = (Answer) o;
return Objects.equals(answer, answer1.answer);
}
@Override
public int hashCode() {
return Objects.hash(answer);
}
}
}
첫번째는 각 학생들과 정답을 객체로 치환을 해서 객체지향적으로 코드를 작성한 답안입니다. 우선은 단순한 정수 배열 비교 문제를 Students, Student, Results, Result, Answer라는 5개의 도메인 클래스로 분리했고 정답객체도 정답을 변수를 객체로 감쌌고,Student 객체에서는 IntPredicate를 사용해서 정답지의 인덱스와 자신의 패턴을 나머지 연산으로 비교를 해서 맞춘 갯수를 계산을 하는 방식이고 마지막에 최고점 산출도 Comparable과 Collections.max를 활용해 객체 간 비교로 처리를 한 방식입니다.
단순히 절차지향대로 코드를 짜는게 아니라 객체지향적인 코드와 스트림을 최대한 활용해서 작성한 답안이었지만 객체지향과 스트림을 연습을 하는데 있어서는 좋은 코드라고 생각이 들었습니다.
3-2.Map을 활용해서 짠 코드
import java.util.*;
class Solution {
public int[] solution(int[] answers) {
int[] answer = {};
List<Integer> p1 = new ArrayList<>();
List<Integer> p2 = new ArrayList<>();
List<Integer> p3 = new ArrayList<>();
int size = answers.length;
int[] p1Ans = {1,2,3,4,5};
int[] p2Ans = {2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5};
int[] p3Ans = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
int p1Size = p1Ans.length;
int p2Size = p2Ans.length;
int p3Size = p3Ans.length;
for(int i = 0 ; i < size; i++) {
p1.add(p1Ans[(i % p1Size)]);
p2.add(p2Ans[(i % p2Size)]);
p3.add(p3Ans[(i % p3Size)]);
}
System.out.println("p1 ===> "+p1.toString());
System.out.println("p2 ===> "+p2.toString());
System.out.println("p3 ===> "+p3.toString());
int p1Score = 0;
int p2Score = 0;
int p3Score = 0;
for(int i = 0 ; i < size ; i++){
if(answers[i] == p1.get(i)) p1Score++;
if(answers[i] == p2.get(i)) p2Score++;
if(answers[i] == p3.get(i)) p3Score++;
}
int maxNum = 0;
List<Integer> cfStore = new ArrayList<>();
cfStore.add(p1Score);
cfStore.add(p2Score);
cfStore.add(p3Score);
for(int i = 0 ; i < cfStore.size();i++) {
if(maxNum < cfStore.get(i)) {
System.out.println("maxNum ===> "+maxNum);
maxNum = cfStore.get(i);
}
}
Map<Integer, Integer> map = new HashMap<>();
map.put(1,p1Score);
map.put(2,p2Score);
map.put(3,p3Score);
List<Map.Entry<Integer, Integer>> entryList = new LinkedList<>(map.entrySet());
entryList.sort(Map.Entry.comparingByValue());
int[] retArr = new int[entryList.size()];
List<Integer> test = new ArrayList<>();
int index = 0 ;
for(Map.Entry<Integer, Integer> entry : entryList){
System.out.println("key : " + entry.getKey() + ", value : " + entry.getValue());
System.out.println("maxNum : " + maxNum + ", getValue : " + entry.getValue());
if(entry.getValue() > maxNum -1) {
retArr[index] = entry.getKey();
test.add(entry.getKey());
}
//retArr[index] = entry.getKey();
index++;
}
int[] test2 = new int[test.size()];
for(int in : retArr) {
System.out.println("retArr : " + in);
}
System.out.println("retArr : " + test.toString());
for(int i = 0 ; i < test.size(); i++) {
test2[i] = test.get(i);
}
return test2;
}
}
다음으로는 Map과 Map.Entry를 활용해서 학생들의 점수를 관리 및 정렬을 한 코드입니다.
리스트를 사용해서 각 학생들의 정답길이를 나머지 연산자를 활용해서 길이를 맞췄고 그 다음으로 각 학생들의 스코어를 계산을 하는 부분은 비슷했지만 마지막 Map을 사용을 했는데 수포자의 번호를 키값으로 점수를 벨류값으로 해서 해시에 담은 뒤에 LinkedList와 Map.Entry.comparingByValue를 사용해서 점수를 기준으로 정렬을 시도한 점입니다.
이 방식으로 했을 경우에는 나중에 점수가 높은 순서대로 데이터를 다루거나 순위를 매길 경우에 확장성이 있게 짤 수 있어보인다는 점이었습니다.
문제 출저
https://school.programmers.co.kr/learn/courses/30/lessons/42840
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
https://school.programmers.co.kr/learn/courses/30/lessons/42840/solution_groups?language=java&page=2
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
'코테 > JAVA' 카테고리의 다른 글
| 프로그래머스-전화번호부 (0) | 2026.07.21 |
|---|---|
| 프로그래머스-기능개발 (0) | 2026.07.20 |
| 프로그래머스-폰켓몬 (0) | 2026.07.17 |
| 프로그래머스-프로세스 (0) | 2026.07.17 |
| 프로그래머스-올바른 괄호 (0) | 2026.07.16 |
