logo

𝝅번째 알파카의 개발 낙서장

screen

[프로그래머스 / JAVA] Level 1 모의고사 (42840)

posts

알고리즘

시리즈 톺아보기

프로그래머스

프로그래머스
count

모의고사 🔗

랭크 사용 언어
Level 1 JAVA

🔗 모의고사

문제 설명 🔗

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 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, 4, 5 ]
  • 2번 수포자 패턴 - [ 2, 1, 2, 3, 2, 4, 2, 5 ]
  • 3번 수포자 패턴 - [ 3, 3, 1, 1, 2, 2, 4, 4, 5, 5 ]

수포자마다 패턴도 다르고, 길이도 달라서 생각없이 접근할 순 없다. 각 패턴의 길이가 다르므로 인덱스 방식은 적절하지 않다. 패턴을 컨테이너 벨트처럼 순환시켜, 가장 앞 쪽의 숫자를 비교하는 것이 더 효과적일 것이다.

이를 위해선 각 수포자별로 패턴을 순환시키는 로직이 필요하다. [ 1, 2, 3, 4, 5 ] -> [ 2, 3, 4, 5, 1 ] 자료구조 중 큐의 특성과 매우 유사하므로, 이 문제는 큐를 적극적으로 활용해볼 생각이다.

각 패턴을 정의할 큐 ONE, TWO, THREE가 있으며, 아래와 같이 초기화를 수행한다.

JAVA

0private void initQueue()
1{
2 ONE.clear();
3 TWO.clear();
4 THREE.clear();
5
6 ONE.add(1);
7 ONE.add(2);
8 ONE.add(3);
9 ONE.add(4);
10 ONE.add(5);
11
12 TWO.add(2);
13 TWO.add(1);
14 TWO.add(2);
15 TWO.add(3);
16 TWO.add(2);
17 TWO.add(4);
18 TWO.add(2);
19 TWO.add(5);
20
21 THREE.add(3);
22 THREE.add(3);
23 THREE.add(1);
24 THREE.add(1);
25 THREE.add(2);
26 THREE.add(2);
27 THREE.add(4);
28 THREE.add(4);
29 THREE.add(5);
30 THREE.add(5);
31}

패턴 순서대로 큐에 데이터를 집어넣는다. poll() 메서드를 통해 가장 앞에 위치한 데이터를 꺼낼 수 있다. poll()의 경우 데이터 호출과 동시에 데이터가 삭제된다.

정답 비교 후, 사용한 데이터는 다시 큐에 집어넣는다. 이런 구조는 문제의 길이에 관계없이 각 수포자 별로 지속적인 순환이 가능할 것이다.

JAVA

0for (int item : answers)
1{
2 int one = Objects.requireNonNull(ONE.poll());
3 int two = Objects.requireNonNull(TWO.poll());
4 int three = Objects.requireNonNull(THREE.poll());
5
6 counts[0] += item == one ? 1 : 0;
7 counts[1] += item == two ? 1 : 0;
8 counts[2] += item == three ? 1 : 0;
9
10 ONE.add(one);
11 TWO.add(two);
12 THREE.add(three);
13}

정답 비교는 위와 같다. Objects.requireNonNullpoll()NullPointerException을 유발할 가능성이 있으므로, 관련 경고를 제거하기 위한 조치다.

각 수포자별 큐에서 패턴을 뽑고, 이를 문제의 정답과 비교하여 맞춘 경우 counts 배열에 카운팅한다.

사용한 패턴은 add 메서드를 통해 큐에 다시 집어넣는 것을 확인할 수 있다.


점수를 모두 구했다면, 가장 고득점을 구하고, 고득점을 맞은 수포자를 반환하면 된다.

counts에서 가장 큰 값을 구하면 아래와 같다.

JAVA

0int max = Arrays.stream(counts).max().getAsInt();

이후 max에 해당하는 점수를 받은 모든 인원을 탐색하여 배열로 나타내면 된다.

코드 🔗

JAVA

0import java.util.ArrayList;
1import java.util.Arrays;
2import java.util.LinkedList;
3import java.util.Objects;
4import java.util.Queue;
5
6/**
7 * 모의고사 클래스
8 *
9 * @author RWB
10 * @since 2021.12.10 Fri 21:43:26
11 */
12class Solution
13{
14 private static final Queue<Integer> ONE = new LinkedList<>();
15 private static final Queue<Integer> TWO = new LinkedList<>();
16 private static final Queue<Integer> THREE = new LinkedList<>();
17
18 /**
19 * 해답 반환 메서드
20 *
21 * @param answers: [int[]] 최고 득점자
22 *
23 * @return [int[]] 해답
24 */
25 public int[] solution(int[] answers)
26 {
27 initQueue();
28
29 int[] counts = { 0, 0, 0 };
30
31 for (int item : answers)
32 {
33 int one = Objects.requireNonNull(ONE.poll());
34 int two = Objects.requireNonNull(TWO.poll());
35 int three = Objects.requireNonNull(THREE.poll());
36
37 counts[0] += item == one ? 1 : 0;
38 counts[1] += item == two ? 1 : 0;
39 counts[2] += item == three ? 1 : 0;
40
41 ONE.add(one);
42 TWO.add(two);
43 THREE.add(three);
44 }
45
46 int max = Arrays.stream(counts).max().getAsInt();
47
48 ArrayList<Integer> list = new ArrayList<>();
49
50 for (int i = 0; i < counts.length; i++)
51 {
52 // 최고 점수를 얻었을 경우
53 if (counts[i] == max)
54 {
55 list.add(i + 1);
56 }
57 }
58
59 return list.stream().mapToInt(Integer::intValue).toArray();
60 }
61
62 /**
63 * 큐 초기화 메서드
64 */
65 private void initQueue()
66 {
67 ONE.clear();
68 TWO.clear();
69 THREE.clear();
70
71 ONE.add(1);
72 ONE.add(2);
73 ONE.add(3);
74 ONE.add(4);
75 ONE.add(5);
76
77 TWO.add(2);
78 TWO.add(1);
79 TWO.add(2);
80 TWO.add(3);
81 TWO.add(2);
82 TWO.add(4);
83 TWO.add(2);
84 TWO.add(5);
85
86 THREE.add(3);
87 THREE.add(3);
88 THREE.add(1);
89 THREE.add(1);
90 THREE.add(2);
91 THREE.add(2);
92 THREE.add(4);
93 THREE.add(4);
94 THREE.add(5);
95 THREE.add(5);
96 }
97}