코딩테스트를 준비할 때 가장 먼저 잡아야 할 것은 두 가지입니다.
첫째, 코테용 빠른 입출력 세팅
둘째, 구현과 시뮬레이션 문제를 푸는 기본 사고 방식
이번 글에서는 1주차 목표와 함께 Java 언어를 이용한 구현 접근 패턴을 정리합니다.
Ⅰ. 목표
Java 코딩테스트에서 기본이 되는 입출력 패턴과 구현·시뮬레이션 문제 흐름을 몸에 익힌다.
구체적으로는 다음 네 가지에 집중해보겠습니다.
- Scanner 대신 BufferedReader / BufferedWriter 사용에 익숙해지기
- 공백으로 구분된 입력 파싱: StringTokenizer / split 패턴 익히기
- StringBuilder를 이용한 출력 최적화
- 구현/시뮬레이션 문제를 단계적으로 쪼개서 코드로 옮기는 연습
Ⅱ. 빠른 입출력 세팅
- 왜 Scanner 대신 BufferedReader를 써야 할까?
코딩테스트에서 입력 데이터가 많을 때 Scanner는 속도가 느려서 시간 초과가 나기 쉽습니다.
대부분의 온라인 저지에서 권장하는 방식은 다음 조합입니다.
- 입력: BufferedReader
- 파싱: StringTokenizer 또는 split
- 출력: StringBuilder + System.out.println 또는 BufferedWriter
이 패턴을 템플릿처럼 만들어 두고, 모든 문제에서 복붙해서 시작하는 습관을 들이면 좋습니다.
- 기본 입출력 템플릿 코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
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));
// 한 줄 읽기
String line = br.readLine(); // 예: "3 5 7"
// 공백 기준으로 파싱
StringTokenizer st = new StringTokenizer(line);
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
// 출력
StringBuilder sb = new StringBuilder();
sb.append(a + b + c).append('\n');
bw.write(sb.toString());
bw.flush();
bw.close();
br.close();
// bw를 쓰고 싶지 않다면 System.out.print(sb);
}
}
여러 번 타이핑해보면서 자연스럽게 외워두는 것을 추천합니다.
Ⅲ. 입력 파싱 패턴
입력 형식에 따라서 StringTokenizer과 split을 자주 사용합니다.
- StringTokenizer
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
- 장점: 간단하고 빠르다.
- 단점: 복잡한 구분자나 빈 문자열 처리에는 약하다.
- 주요 메서드
- boolean hasMoreTokens(): 현재 위치 뒤에 처리할 토큰이 남았으면 true, 없으면 false 반환
- String nextToken(): 다음 토큰을 문자열로 반환
- String nextToken(delim): 지정된 구분자(delim) 기준으로 다음 토큰을 반환
- split
split은 정규식을 기반으로 나누기 때문에 조금 더 유연하지만, 상대적으로 느릴 수 있습니다.
String[] parts = br.readLine().split(" ");
int n = Integer.parseInt(parts[0]);
int m = Integer.parseInt(parts[1]);
- 장점: 코드가 직관적이고 디버깅이 쉽다.
- 단점: 입력이 많을 때는 성능이 떨어질 수 있다.
두 가지 방식 모두 연습해보고,
입력이 많은 문제에서는 StringTokenizer를 기본 선택으로 가져가는 흐름을 목표로 하면 좋습니다.
Ⅳ. 구현 및 시뮬레이션 문제 접근법
구현/시뮬레이션 문제는 알고리즘 아이디어가 어렵다기보다는 문제를 얼마나 꼼꼼히 코드로 옮기느냐가 핵심입니다.
다음 네 가지 습관을 들이는 것이 좋습니다.
- 문제를 단계로 쪼갠다
- 상태를 나타내는 변수들을 먼저 정의한다.
- 시간 위치 점수 등의 변화 규칙을 문장으로 적어본다.
- 그 문장을 그대로 반복문, 조건문으로 옮긴다.
- 예시: 점수 계산 시뮬레이션
예를 들어, 다음과 같은 문제를 생각해볼 수 있습니다.
N번의 시험 점수가 주어지고,
40점 미만인 점수는 40점으로 처리한 뒤,
평균 점수를 출력하는 문제
이를 구현 문제로 보면 필요한 단계는 다음과 같습니다.
- N 입력
- N개의 점수 입력
- 각 점수가 40점 미만이면 40으로 처리
- 합계를 구하고 N으로 나눔
- 결과 출력
이걸 그대로 Java 코드로 옮기면 다음과 같습니다.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine()); // 시험 횟수
int sum = 0;
StringTokenizer st = new StringTokenizer(br.readLine());
while(st.hasMoreTokens()) {
int score = Integer.parseInt(st.nextToken());
if (score < 40) {
score = 40;
}
sum += score;
}
int avg = sum / n;
System.out.println(avg);
}
}
여기서 중요한 포인트는 알고리즘보다는
문제의 요구사항을 빠뜨리지 않고 그대로 코드로 옮기는 연습입니다.
- 예시: 시간 증가 시뮬레이션 패턴
시뮬레이션 문제에서 자주 나오는 유형 중 하나가 시간 계산입니다.
현재 시각 H:M이 주어지고, T분 뒤의 시간을 구하는 문제
- H, M, T 입력
- M += T
- H += M / 60
- M = M % 60
- H = H % 24
이 과정을 그대로 코드로 옮기면 아래와 같습니다.
StringTokenizer st = new StringTokenizer(br.readLine());
int h = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
// 추가할 분
int t = Integer.parseInt(br.readLine());
m += t;
h += m / 60;
m %= 60;
h %= 24;
System.out.println(h + " " + m);
Ⅴ. StringBuilder를 이용한 출력 최적화
여러 줄을 출력해야 하는 문제에서는 System.out.println을 매번 호출하는 것보다,
StringBuilder에 모아서 마지막에 한 번에 출력하는 것이 좋습니다.
- 기본 패턴
StringBuilder sb = new StringBuilder();
for (int i=0; i<n; i++) {
sb.append().append('\n');
}
System.out.print(sb);
- 언제 쓰면 좋은가
- 반복문 안에서 출력이 많이 필요한 문제
- 그래프 탐색 결과, DP 테이블 결과 등 여러 줄 출력
- 온라인 저지에서 시간 초과를 피하고 싶을 때
1주차에는 반복문 안에서 println 남발하지 말고,
StringBuilder로 모은 뒤 한 번에 출력하는 습관을 들이는 것만으로도 큰 차이가 납니다.
Ⅵ. 체크리스트
- BufferedReader + StringTokenizer 조합으로 입력 템플릿을 외워서 쓸 수 있다.
- split(" ")과 StringTokenizer 둘 다 써봤고, 차이를 설명할 수 있다.
- StringBuilder로 여러 줄 출력 코드를 작성할 수 있다.
- 간단한 구현 문제(점수 계산, 시간 계산, 배열 합 등)를 문제 설명 없이 코드만 보고도 이해할 수 있다.
- 구현/시뮬레이션 문제를 단계 → 상태 변수 → 반복문/조건문 순서로 쪼개는 습관이 생겼다.
Ⅶ. 마무리
자바를 이용한 코딩테스트 기본 환경을 설정하고,
구현 및 시뮬레이션 문제를 다루는 감각을 만드는 데 집중해보았습니다.
다음 글에서는 배열, 문자열을 조금 더 다양하게 다루는 방법과
완전 탐색(Brute Force)을 이용한 문제 풀이 패턴을 정리하면서
가능한 경우를 전부 돌려보는 알고리즘을 자바 코드로 구현하는 연습을 해보겠습니다.
'Algorithm > 정리' 카테고리의 다른 글
| [코딩테스트] 정렬, 이진 탐색, 누적합 프로그래머스 문제 모음 (0) | 2025.12.10 |
|---|---|
| [코딩테스트] 정렬, 이진 탐색, 누적합으로 시간 복잡도 줄이기 (0) | 2025.12.10 |
| [코딩테스트] 스택, 큐, 덱, 우선순위 큐 자료구조 정리 (0) | 2025.12.09 |
| [코딩테스트] 배열, 문자열과 완전 탐색(Brute Force) (0) | 2025.12.09 |