
내가 생각했을때 문제에서 원하는부분
첫 번째 줄에 돌돌이가 외운 아이템의 종류의 수 N(1 ≤ N ≤ 100000)과 자작나무를 뜻하는 단어 S가 공백으로 구분되어 주어진다.
S의 길이는 1 이상 50 이하이며, 영어 소문자로만 이루어져 있다.
두 번째 줄부터 N+1번째 줄까지 아이템의 이름과 수량이 공백으로 구분되어 주어진다.
각 아이템의 이름은 50글자를 넘지 않는다.
수량은 1 이상 64 이하의 정수이다.
아이템의 이름은 중복되지 않는다.
또한, 아이템의 이름은 구분자로 시작하거나 끝나지 않고, 구분자가 두 번 이상 연속으로 주어지지 않는다.
게임에서 삭제된 아이템의 총 수량을 출력한다.
내가 이 문제를 보고 생각해본 부분
입력 준비 (BufferedReader, StringTokenizer):
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
많은 양의 데이터를 효율적으로 읽기 위해 BufferedReader를 사용한다.
StringTokenizer st = new StringTokenizer(br.readLine());
첫 번째 줄에서 N(아이템 종류의 수)과 S(삭제될 단어)를 읽어온다.
StringTokenizer는 문자열을 공백(기본 구분자)을 기준으로 나누어 토큰을 하나씩 가져오는 데 유용한다.
초기 변수 설정:
int N = Integer.parseInt(st.nextToken());
N 값을 정수로 변환하여 저장한다.
String S = st.nextToken();
삭제 기준이 되는 단어 S를 저장한다.
long totalDeletedQuantity = 0;
삭제된 아이템의 총 수량을 저장할 변수이다.
아이템 수량이 최대 64이고 N이 최대 10만 개이므로, 64 * 100,000 = 6,400,000이 된다.
이는 int의 범위를 충분히 넘어서지 않지만, 혹시 모를 경우를 대비하여 더 큰 long 타입을 사용하는 것이 안전한다.
보통 합계 계산 시에는 long을 선호한다.
아이템 정보 반복 처리:
for (int i = 0; i < N; i++) { ... }
N번 반복하여 각 아이템의 이름과 수량을 처리한다.
st = new StringTokenizer(br.readLine());
각 줄에서 아이템 이름과 수량을 다시 StringTokenizer로 분리한다.
String itemName = st.nextToken();
int quantity = Integer.parseInt(st.nextToken());
아이템 이름과 수량을 각각 변수에 저장한다.
아이템 이름 단어 분리 및 S 포함 여부 확인:
StringTokenizer nameTokens = new StringTokenizer(itemName, "_");
아이템 이름 itemName을 _ (언더스코어)를 구분자로 사용하여 다시 StringTokenizer로 분리한다.
이렇게 하면 stone_axe는 ["stone", "axe"]로, cobblestone은 ["cobblestone"]으로 단어 단위로 나뉘게 된다.
boolean containsS = false;
현재 아이템 이름이 S를 포함하는지 추적하기 위한 플래그 변수이다.
while (nameTokens.hasMoreTokens()) { ... }
아이템 이름에서 분리된 각 단어에 대해 반복한다.
if (nameTokens.nextToken().equals(S)) { ... }
nameTokens.nextToken()으로 다음 단어를 가져온 후, 이 단어가 우리가 찾는 S와 equals() 메서드를 이용해 정확히 일치하는지 확인한다.
equals()를 사용해야 "cobblestone" 안에 "stone"이 들어있다고 판단하지 않고, 오직 단어 자체가 "stone"인 경우만 찾아낸다.
containsS = true; break;
만약 S와 일치하는 단어를 찾았다면, 이 아이템은 삭제 대상이므로 containsS를 true로 설정하고 break를 통해 현재 아이템 이름의 단어 확인 루프를 바로 종료한다.
더 이상 다른 단어를 확인할 필요가 없기 때문이다.
삭제된 수량 합산:
if (containsS) { totalDeletedQuantity += quantity; }
아이템 이름에 S가 포함되었다고(containsS가 true) 판단되면, 해당 아이템의 quantity를 totalDeletedQuantity에 더해준다.
결과 출력 및 자원 해제:
System.out.println(totalDeletedQuantity);
모든 아이템 처리가 끝나면 최종 합산된 totalDeletedQuantity를 출력한다.
br.close();
사용한 BufferedReader를 닫아 시스템 자원 누수를 방지한다.
코드로 구현
package baekjoon.baekjoon_32;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
// 백준 31496번 문제
public class Main1257 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 첫 번째 줄에서 N과 S를 읽습니다.
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
String S = st.nextToken(); // 자작나무를 뜻하는 단어 S
long totalDeletedQuantity = 0; // 삭제된 아이템의 총 수량을 저장할 변수 (수량이 많을 수 있으므로 long 사용)
// N개의 아이템 정보를 읽고 처리합니다.
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
String itemName = st.nextToken(); // 아이템 이름
int quantity = Integer.parseInt(st.nextToken()); // 아이템 수량
// 아이템 이름을 '_' 기준으로 분리하여 단어들을 확인합니다.
// String.split("_") 대신 StringTokenizer를 사용하여 성능을 최적화할 수 있습니다.
StringTokenizer nameTokens = new StringTokenizer(itemName, "_");
boolean containsS = false; // 현재 아이템 이름에 S가 포함되는지 여부
while (nameTokens.hasMoreTokens()) {
if (nameTokens.nextToken().equals(S)) {
containsS = true; // S와 일치하는 단어를 찾으면 true로 설정하고
break; // 더 이상 확인할 필요가 없으므로 반복을 종료합니다.
}
}
// S를 포함하는 아이템이라면 총 수량에 더해줍니다.
if (containsS) {
totalDeletedQuantity += quantity;
}
}
// 삭제된 아이템의 총 수량을 출력합니다.
System.out.println(totalDeletedQuantity);
br.close(); // BufferedReader를 닫아 자원을 해제합니다.
}
}
코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.