백준 알고리즘 문제를 해결하다보니 처음에 가장 많이 어려웠던게
프로그래머스는 함수의 매개변수와 반환값으로 입출력을 처리하지만, 백준은 표준 입출력(System.in, System.out)을 직접 다루어야 한다는 차이가 있다.
프로그래머스에 익숙했던 나는 직관적이지 못한 테스트 방법 때문에 많은 어려움이 있었지만
지인에게 아주 좋은 베이스 템플릿을 공유받아 활용하면서 백준의 빠른 입출력을 위한 기능들을 새로 알게되었고, 이에 대해 명확하게 이해하는 과정을 가져보려한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N;
// 자주 사용되는 Integer.parseInt()를 간편하게 사용하기 위한 메서드
static int toInt(String s) {
return Integer.parseInt(s);
}
// BufferedReader 사용 시에는 IOException나 try-catch로 예외처리 해야 함
public static void main(String[] args) throws IOException {
// 입력을 BufferedReader를 통해 받음
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 문제에서 입력받은 한 줄을 공백 기준으로 나눔
StringTokenizer st = new StringTokenizer(br.readLine());
// 첫 토큰의 정수형
N = toInt(st.nextToken());
}
}
백준 문제는 보통
이와같이 입력값을 공백 기준으로 많이 주어지기 때문에 StringTokenizer가 많이 사용된다.
이를 바탕으로 백준의 '빠른 A+B'라는 문제를 해결해보겠다.
문제 : Java를 사용하고 있다면, Scanner와 System.out.println 대신 BufferedReader와 BufferedWriter를 사용할 수 있다. BufferedWriter.flush는 맨 마지막에 한 번만 하면 된다.
또한 입력과 출력 스트림은 별개이므로, 테스트케이스를 전부 입력받아서 저장한 뒤 전부 출력할 필요는 없다. 테스트케이스를 하나 받은 뒤 하나 출력해도 된다.
첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다.
각 테스트케이스마다 A+B를 한 줄에 하나씩 순서대로 출력한다.
# 예제 입력 1
5
1 1
12 34
5 500
40 60
1000 1000
# 예제 출력 1
2
46
505
100
2000
여기서 주요 정보는 테스트케이스 개수인 T의 범위가 최대 1,000,000이라서 처리 속도가 중요하다는 것이다.
보통 일반적으로 자주 사용했던 Scanner
와 System.out.println
은 직관적이지만 속도가 느려 대량의 데이터를 처리하는데 적합하지 못하다.
BufferedReader : 문자 기반 입력 스트림으로, 입력을 버퍼에 모아두었다가 한 줄씩 읽어(readLine()
) 빠른 속도가 가능하지만 String 형태로 반환되므로 필요에 따라 정수형으로 파싱이 필요하다.
BufferedWriter : 문자 기반 출력 스트림으로, 출력을 버퍼에 모아두었다가 한번에 처리가 가능하다.
\n
으로 개행 처리가 가능하고, flush()
를 사용해 한 번에 출력이 가능하다.
StringTokenizer : 문자열을 지정된 구분자(공백) 기준으로 빠르게 나누는 데 사용된다.
.nextToken()
을 사용해서 구분자로 나누어진 토큰을 순차적으로 호출하여 사용할 수 있다.
만약 토큰 개수보다 더 호출하게되면 NoSuchElementException
이 발생한다.(테스트하면서 실수해서 은근히 많이봄)
import java.io.*;
import java.util.StringTokenizer;
public class Test_07_FastAPlusB {
static int toInt(String s) {
return Integer.parseInt(s);
}
public static void main(String[] args) throws IOException {
// 빠른 입/출력을 위해 BufferedReader와 BufferedWriter 사용
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
// for문을 돌려야 하므로 T값을 저장
int t = toInt(br.readLine());
for (int i = 0; i < t; i++) {
// StringTokenizer로 각 줄의 A와 B의 값을 나누기
StringTokenizer st = new StringTokenizer(br.readLine());
// A와 B의 값을 정수형으로 변환(toInt 메서드)
int sum = toInt(st.nextToken()) + toInt(st.nextToken());
// 한번에 출력하기 위해 bw에 저장하고 개행
bw.write(sum + "\n");
}
// flush()로 작성된 BufferedWriter를 한번에 출력
bw.flush();
// 더 이상의 출력이 없으므로 자원을 해제하기 위해 호출
bw.close();
}
}