문제
(...너무 길어서 생략...)
오박사 : 그럼 다솜아 이제 진정한 포켓몬 마스터가 되기 위해 도감을 완성시키도록 하여라. 일단 네가 현재 가지고 있는 포켓몬 도감에서 포켓몬의 이름을 보면 포켓몬의 번호를 말하거나, 포켓몬의 번호를 보면 포켓몬의 이름을 말하는 연습을 하도록 하여라. 나의 시험을 통과하면, 내가 새로 만든 도감을 주도록 하겠네.
입력
첫째 줄에는 도감에 수록되어 있는 포켓몬의 개수 N이랑 내가 맞춰야 하는 문제의 개수 M이 주어져. N과 M은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수인데, 자연수가 뭔지는 알지? 모르면 물어봐도 괜찮아. 나는 언제든지 질문에 답해줄 준비가 되어있어.
둘째 줄부터 N개의 줄에 포켓몬의 번호가 1번인 포켓몬부터 N번에 해당하는 포켓몬까지 한 줄에 하나씩 입력으로 들어와. 포켓몬의 이름은 모두 영어로만 이루어져있고, 또, 음... 첫 글자만 대문자이고, 나머지 문자는 소문자로만 이루어져 있어. 아참! 일부 포켓몬은 마지막 문자만 대문자일 수도 있어. 포켓몬 이름의 최대 길이는 20, 최소 길이는 2야. 그 다음 줄부터 총 M개의 줄에 내가 맞춰야하는 문제가 입력으로 들어와. 문제가 알파벳으로만 들어오면 포켓몬 번호를 말해야 하고, 숫자로만 들어오면, 포켓몬 번호에 해당하는 문자를 출력해야해. 입력으로 들어오는 숫자는 반드시 1보다 크거나 같고, N보다 작거나 같고, 입력으로 들어오는 문자는 반드시 도감에 있는 포켓몬의 이름만 주어져. 그럼 화이팅!!!
출력
첫째 줄부터 차례대로 M개의 줄에 각각의 문제에 대한 답을 말해줬으면 좋겠어!!!. 입력으로 숫자가 들어왔다면 그 숫자에 해당하는 포켓몬의 이름을, 문자가 들어왔으면 그 포켓몬의 이름에 해당하는 번호를 출력하면 돼. 그럼 땡큐~

이게 오박사님이 나에게 새로 주시려고 하는 도감이야. 너무 가지고 싶다ㅠㅜ. 꼭 만점을 받아줬으면 좋겠어!! 파이팅!!!
예제 입력 1
26 5
Bulbasaur
Ivysaur
Venusaur
Charmander
Charmeleon
Charizard
Squirtle
Wartortle
Blastoise
Caterpie
Metapod
Butterfree
Weedle
Kakuna
Beedrill
Pidgey
Pidgeotto
Pidgeot
Rattata
Raticate
Spearow
Fearow
Ekans
Arbok
Pikachu
Raichu
25
Raichu
3
Pidgey
Kakuna
예제 출력 1
Pikachu
26
Venusaur
16
14
📝 제출 답안
❌ 오답
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
HashMap<String, Integer> pokemon = new HashMap<>();
for (int i = 1; i <= n; i++) {
String input = br.readLine();
pokemon.put(input, i);
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < m; i++) {
String quest = br.readLine();
if (quest.chars().allMatch(Character::isDigit)) {
sb.append(getKey(pokemon, Integer.parseInt(quest))).append("\n");
} else {
sb.append(pokemon.get(quest)).append("\n");
}
}
bw.write(sb.toString());
bw.flush();
}
public static <K, V> K getKey(Map<K, V> map, V value) {
for (K key : map.keySet()) {
if (value.equals(map.get(key))) {
return key;
}
}
return null;
}
}
⭕ 정답
import java.io.*;
import java.util.HashMap;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
HashMap<String, Integer> pokemonNameKey = new HashMap<>();
HashMap<Integer, String> pokemonNumberKey = new HashMap<>();
for (int i = 1; i <= n; i++) {
String input = br.readLine();
pokemonNameKey.put(input, i);
pokemonNumberKey.put(i, input);
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < m; i++) {
String quest = br.readLine();
if (quest.chars().allMatch(Character::isDigit)) {
sb.append(pokemonNumberKey.get(Integer.parseInt(quest))).append("\n");
} else {
sb.append(pokemonNameKey.get(quest)).append("\n");
}
}
bw.write(sb.toString());
bw.flush();
}
}
나도 드디어 다솜이 문제 풀었당히히
우선 이 문제는 포켓몬의 이름과 번호를 같이 저장해두고 입력값으로 이름이 들어왔을 땐 포켓몬 번호를 반환하고,
포켓몬 번호가 들어왔을 땐 포켓몬 이름을 반환해주어야 한다.
String 타입인 이름과 Integer 타입인 번호를 같이 저장하기 위해 HashMap을 사용하였다.
하지만 HashMap은 key로 value를 찾는 것만 가능하기 때문에 구글링을 통해 value 값으로 key 값을 찾는 방법을 알아냈다. 처음 코드는 그렇게 getKey 메서드로 value로 key를 찾는 방법을 구현했다. 그러나 시간 초과가 나와서 실패했다.
처음 코드의 비효율적인 부분은 당연히도 getKey 메서드였다.
getKey 메서드는 HashMap의 키를 검색하기 위해 모든 키를 순회하면서 값을 비교한다. 이는 시간 복잡도 O(n)을 가지므로 질문 수가 많을수록 비효율적으로 동작하는 것이다.
기본적으로 HashMap의 빠른 조회 성능은 O(1)의 시간 복잡도를 가지므로 효율성을 제대로 사용하지 못하고 있던 것이다.
그래서 다른 사람들이 푼 거 찾아보다보니 양방향으로 관리하도록 HashMap을 2개 만들었길래 나도 도전해봤다.
두 개의 HashMap을 사용해서 하나는 이름을 key로 번호를 value로 저장하였고,
반대로 하나는 번호를 key로 이름을 value로 저장하였다.
그 외에 코드는 그대로 가져갔다.
BufferedReader와 StringTokenizer 입력을 받아 이름과 순서를 두 개의 HashMap에 순서대로 저장해준다.
문제를 입력 받아 입력값이 숫자이면 번호를 key 값으로 저장해 둔 pokemonNumberKey에서 value를 찾아 이름을 StringBuilder에 추가하고, 아니면 이름을 key 값으로 저장해 둔 pokemonNameKey에서 value를 찾아 번호를 sb에 추가해준다.
오늘은 출력 시에도 BufferdWriter를 사용해서 출력 효율을 높이고자 했다. 그동안은 입력만 BufferedReader로 받아오고 System.out.println으로 출력해주었는데, 출력도 맞춰주었다. 문자열 출력과 관련된 내용은 이전에 기록해둔 것이 있어서 링크 첨부로 대신했다.
🔗 BufferedReader와 BufferedWriter 사용하기
https://aaahyunseo.tistory.com/4
[JAVA] BufferedReader와 Bufferedwriter
백준 15552번 문제를 풀던 중BufferedReader와 Bufferedwriter를이용해 문제를 풀라고 하길래급하게 배워보는 중BufferedReader: Scanner 대신 사용 가능※주의할 점은 데이터를 받을 때enter로만 구분 가능하
aaahyunseo.tistory.com
'백엔드개발 > Baekjoon' 카테고리의 다른 글
[Baekjoon] 1764 듣보잡 - JAVA (0) | 2025.01.11 |
---|---|
[Baekjoon] 17219 비밀번호 찾기 - JAVA (0) | 2025.01.11 |
[Baekjoon] 1463 1로 만들기 - JAVA (0) | 2025.01.09 |
[Baekjoon] 1260 DFS와 BFS - JAVA (0) | 2025.01.07 |
[Baekjoon] 1003 피보나치 수열 - JAVA (0) | 2025.01.06 |