Java 코딩테스트 완벽 가이드 - Part 1: 입출력 최적화의 모든 것
코딩테스트에서 가장 먼저 마주치는 것이 바로 입출력이다. 특히 백준에서는 입출력 처리 방식에 따라 시간 초과가 날 수 있어 최적화된 입출력 방식을 아는 것이 중요하다. 이 글에서는 Java로 코딩테스트를 준비하는 분들을 위해 입출력 처리 방법을 상세히 설명한다.
1. Scanner vs BufferedReader
많은 초보자들이 Scanner를 사용하지만, 대부분의 경우 BufferedReader를 사용하는 것이 좋다. 그 이유를 살펴보자.
BufferedReader의 장점
- 버퍼 사용으로 인한 속도 향상
- Scanner는 내부적으로 정규표현식을 사용하여 문자열을 파싱한다
- BufferedReader는 버퍼에 일정량의 데이터를 모아서 한 번에 처리한다
- 대량의 데이터 처리 시 최대 5배까지 성능 차이가 난다
- 메모리 사용량 감소
- Scanner는 입력 데이터를 다양한 타입으로 파싱하기 위한 부가적인 객체들을 생성한다
- BufferedReader는 단순히 문자열로만 읽어들여 메모리 사용이 효율적이다
2. 기본 입출력 템플릿
다음은 코딩테스트에서 바로 사용할 수 있는 표준 템플릿이다:
import java.io.*;
import java.util.*;
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));
// 한 줄 읽기
String line = br.readLine();
// 공백으로 구분된 정수들 읽기
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
// 결과 출력
bw.write(String.valueOf(n + m));
bw.newLine();
// 버퍼 비우기
bw.flush();
br.close();
bw.close();
}
}
3. 자주 사용되는 입력 패턴
3.1 정수 배열 입력받기
// N개의 정수를 배열로 입력받기
int N = Integer.parseInt(br.readLine());
int[] arr = new int[N];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
3.2 2차원 배열 입력받기
// N x M 크기의 2차원 배열 입력받기
int N = Integer.parseInt(br.readLine());
int M = Integer.parseInt(br.readLine());
int[][] arr = new int[N][M];
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
arr[i][j] = Integer.parseInt(st.nextToken());
}
}
4. 주의사항 및 팁
- IOException 처리
- main 메소드에 throws IOException을 반드시 추가한다
- try-catch문을 사용할 경우 코드가 길어지므로 권장하지 않는다
- BufferedWriter 사용 시 주의점
- write() 메소드는 String 타입만 받는다
- 숫자를 출력할 때는 String.valueOf()를 사용한다
- 마지막에 반드시 flush()를 호출해야 한다
- 메모리 관리
- 입력이 많은 경우 StringBuilder를 활용하여 문자열을 한 번에 출력한다
- 더 이상 사용하지 않는 객체는 null 처리하여 GC를 돕는다
Java 코딩테스트 필수 입출력 - 더 쉽게, 더 깔끔하게
코딩테스트를 준비하다 보면 입출력 코드가 너무 길어 실제 문제 해결 로직에 집중하기 어려울 때가 있다. 상황별로 가장 간단하게 사용할 수 있는 입출력 방법을 유형별로 분류했다.
1. 기본 템플릿 - 가장 간단한 버전
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
// 여기에 문제 해결 로직 작성
System.out.println(sb);
}
}
이 템플릿의 장점:
- BufferedWriter 없이 StringBuilder로 출력 관리
- close() 호출 불필요
- flush() 호출 불필요
- 코드가 짧고 깔끔함
2. 입력 패턴별 최적화 코드
2.1 한 줄에 여러 정수 입력
// 방법 1: StringTokenizer 사용
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
// 방법 2: split() 사용
String[] input = br.readLine().split(" ");
int N = Integer.parseInt(input[0]);
int M = Integer.parseInt(input[1]);
2.2 여러 줄의 입력 처리
// 입력 개수가 주어진 경우
int T = Integer.parseInt(br.readLine());
for(int t = 0; t < T; t++) {
String line = br.readLine();
sb.append(line).append('\n');
}
// 입력 개수가 정해지지 않은 경우
String line;
while((line = br.readLine()) != null) {
sb.append(line).append('\n');
}
3. 상황별 추천 방식
1. 단순 출력이 많은 경우
StringBuilder sb = new StringBuilder();
// ... 로직 ...
sb.append(결과).append('\n');
System.out.println(sb);
2. 정수 계산 결과만 출력하는 경우
System.out.println(결과);
3. 테스트 케이스가 많은 경우
int T = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
for(int t = 0; t < T; t++) {
// ... 로직 ...
sb.append(결과).append('\n');
}
System.out.println(sb);
4. 결론 및 추천사항
- 대부분의 경우
StringBuilder + System.out.println
조합이면 충분하다. - 입력은
BufferedReader
를 기본으로 사용한다. - 특별한 이유가 없다면 close()나 flush()는 생략 가능하다.
- 극단적인 성능이 필요한 경우에만 BufferedWriter를 고려한다.
이렇게 간단한 버전의 입출력 템플릿을 사용하면 코드가 더 깔끔해지고, 실제 문제 해결에 더 집중할 수 있다.
마무리
입출력은 모든 코딩테스트 문제의 기본이다. BufferedReader와 BufferedWriter를 사용한 최적화된 입출력 처리는 실행 시간을 크게 단축시킬 수 있다.
참고자료
- Java API Documentation: BufferedReader
- Java API Documentation: BufferedWriter
- 백준 온라인 저지: 빠른 A+B (15552번)
- Java API Documentation: StringBuilder
- 백준 온라인 저지: A+B (1000번)
'DSA > 코딩테스트' 카테고리의 다른 글
Java 코딩테스트 완벽 가이드 - Part 2: 필수 메서드 및 시간복잡도 총정리 (1) | 2025.01.22 |
---|---|
Java 코딩테스트 완벽 가이드 Part 1. 입출력 심화 - Scanner와 BufferedReader의 동작 원리 (0) | 2025.01.22 |
99클럽 코테 스터디 7일차 TIL - Java 백준 15829 해싱 (1) | 2025.01.22 |
99클럽 코테 스터디 6일차 TIL - Java 백준 27160번 할리갈리 (2) | 2025.01.22 |
99클럽 코테 스터디 5일차 TIL - Java 백준 P10798 세로 읽기 (0) | 2025.01.17 |