문제
최근 아시아 지역의 학생들만 참여하는 정보 올림피아드 대회가 만들어졌다. 이 대회는 온라인으로 치러지기 때문에 각 나라에서 이 대회에 참여하는 학생 수의 제한은 없다.
참여한 학생들의 성적순서대로 세 명에게만 금, 은, 동메달을 수여한다. 단, 동점자는 없다고 가정한다. 그리고 나라별 메달 수는 최대 두 개다.
예를 들어, 대회 결과가 다음의 표와 같이 주어졌다고 하자.
| 참가국 | 학생번호 | 점수 |
|---|---|---|
| 1 | 1 | 230 |
| 1 | 2 | 210 |
| 1 | 3 | 205 |
| 2 | 1 | 100 |
| 2 | 2 | 150 |
| 3 | 1 | 175 |
| 3 | 2 | 190 |
| 3 | 3 | 180 |
| 3 | 4 | 195 |
이 경우, 금메달 수상자는 1번 국가의 1번 학생이고, 은메달 수상자는 1번 국가의 2번 학생이며, 동메달 수상자는 3번 국가의 4번 학생이다. (1번 국가의 3번 학생의 성적이 동메달 수여자보다 높지만, 나라 별 메달 수가 두 개 이하 이므로 1번 국가 3번 학생은 동메달을 받을 수 없다.)
대회 결과가 입력으로 주어질 때, 메달 수상자를 결정하여 출력하는 프로그램을 작성하시오.
입력
첫 번째 줄에는 대회참가 학생 수를 나타내는 N이 주어진다. 단, 3 ≤ N ≤ 100이다. 두 번째 줄부터 N개의 줄에는 각 줄마다 한 학생의 소속 국가 번호, 학생 번호, 그리고 성적이 하나의 빈칸을 사이에 두고 주어진다. 단, 국가 번호는 1부터 순서대로 하나의 정수로 주어지며, 각 학생번호는 각 나라별로 1부터 순서대로 하나의 정수로 주어진다, 점수는 0 이상 1000 이하의 정수이고, 동점자는 없다고 가정한다. 입력으로 제공되는 국가는 적어도 두 나라 이상이다.
출력
메달을 받는 학생들을 금, 은, 동메달 순서대로 한 줄에 한 명씩 출력한다. 즉, 첫 번째 줄에는 금메달 수상자를, 두 번째 줄에는 은메달 수상자를, 세 번째 줄에는 동메달 수상자를 출력한다. 하나의 줄에는 소속국가 번호와 학생 번호를 하나의 빈칸을 사이에 두고 출력한다.
풀이
점수 순으로 메달을 주되, 같은 나라에서 최대 두 명까지만 받을 수 있다. 그래서 참가자들을 점수 내림차순으로 정렬한 뒤, 나라별로 몇 명이 이미 선발됐는지 세면서 앞에서부터 세 명을 뽑으면 된다.
현재 코드는 정렬 이후 국가별 카운트를 확인하며 메달리스트를 결정한다. 정렬이 끝나면 남는 조건은 '이 나라가 이미 두 번 나왔는가' 하나뿐이라 흐름이 꽤 단순하다.
코드
import java.io.*;
import java.util.*;
public class Main {
static class Node {
int country, number, score;
Node(int country, int number, int score) {
this.country = country;
this.number = number;
this.score = score;
}
}
private static Node[] nodes;
private static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int N = Integer.parseInt(br.readLine());
nodes = new Node[N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
int country = Integer.parseInt(st.nextToken());
int number = Integer.parseInt(st.nextToken());
int score = Integer.parseInt(st.nextToken());
nodes[i] = new Node(country, number, score);
}
Arrays.sort(nodes, (n1, n2) -> n2.score - n1.score);
solve(N);
System.out.println(sb);
}
private static void solve(int N) {
int cnt = 0;
int[] count = new int[N + 1];
for (Node node : nodes) {
if (cnt == 3) break;
if (count[node.country] == 2) continue;
sb.append(node.country).append(" ").append(node.number).append('\n');
cnt++;
count[node.country]++;
}
}
}복잡도
- 시간 복잡도: 학생 기록을 점수 기준으로 정렬하므로 이다.
- 공간 복잡도: 학생 기록을 저장하므로 이다.
마무리
점수 내림차순으로 훑되 나라별 선발 수만 제한하면 된다. 이미 두 명을 뽑은 나라는 건너뛰고 세 명이 채워지는 순간 멈추면 답이 완성된다.
