
>>문제 바로가기<<
정답률 45.4%의 입출력 문제이다.
손에 익숙해진 Scanner/print 사용 대신
BufferedReader, BufferedWriter, Tokenizer을 사용해야하는 문제다.
Scanner는 간편하고 좋은 도구지만,
이 문제에는 "시간제한"이 걸려있다.
Scanner를 사용한 속도로는 최대 100만개의 일을 수행하기엔 처리가 느려,
더 빠른 도구를 사용해야한다.
만약 10개의 택배를 주문했다고 해보자.
Scanner 방식은 택배를 하나하나 따로 받는 방식이고
Buffered I/O 방식은 택배 10개를 한 번에 받는 방식이다.
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
int a, b;
for(int i=0; i<T; i++){
a = sc.nextInt();
b = sc.nextInt();
System.out.println(a+b);
}
sc.close();
}
}
예시로 다음 코드를 보자.
Scanner와 println를 이용해 a+b를 T번 출력하는 코드이다.
더한걸 출력하러 갔다가 다시 입력받으러 되돌아오고
더한걸 출력하러 갔다가 다시 입력받으러 되돌아오고
더한걸 출력하러 갔다가 다시 입력받으러 되돌아오고...
컴퓨터 입장에서 셔틀런을 뛰는 느낌일것이다.
T가 계속해서 숫자가 커지면
그만큼 지연시간도 커지기때문에 해당 문제의 제한시간에 맞추지 못한다.
때문에 출력하러 왔다갔다 할 필요 없이
같은 장소에서 계속 모아놨다가 한번에 가서 출력하는 Buffered I/O가
훨씬 빠르고 문제의 취지에 적합하다.
그럼 지금부터 하나씩 코드를 짜보도록 하자.
완성 코드는 글의 맨 아래쪽에 적어두었다.
import java.io.*;
import java.util.StringTokenizer;
우선 평소에 사용하던 Scanner 대신 io를 불러와야한다.
StringTokenizer는 buffered 기능을 효과적으로 사용하기위해 필요하다.
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;
int T = Integer.parseInt(br.readLine());
for(int i = 0; i<T; i++){
st = new StringTokenizer(br.readLine(), " ");
bw.write((Integer.parseInt(st.nextToken()) + Integer.parseInt(st.nextToken())) + "\n");
}
br.close();
bw.flush();
bw.close();
}
}
입력된 글 "한 줄"을 통째로 잡아 (br.readLine())
정수형 함수로 변환하고 (Integer.parseInt())
정수 T에다가 집어넣는 코드이다.
그건 BufferedReader.readLine() << 이녀석이
항상 문자열(String)로 반환하기 때문이다.
123을 입력하면 "123"이 들어가기 때문에
정수형으로의 변환이 필요하다.
StringTokenrizer로 새로 선언한 변수 st에
입력된 글 "한 줄"을 통째로 잡아 (br.readLine())
공백 (" ")을 기준으로 나눠 st에 하나하나씩 저장한다.
이때 st를
엄밀히 말하면 배열은 아니지만, 배열로 상상해도 무관하다.
만약 1 3을 입력했으면 공백을 기준으로 나눠서
st[0]에 1, st[1]에 3 이 저장된다.
Token으로 나눠진 st[0]과 st[1]을 (st.nextToken())
정수형으로 바꿔 둘이 더해서 (Integer.parseInt())
BufferedWriter(출력버퍼) bw에 "저장"한다. (bw.write())
Buffered I/O를 쓴 목적답게
바로 출력을 하는것이 아니라 출력버퍼에 "저장"한다.
br.close();
bw.flush();
bw.close();
입력버퍼 br을 종료하고
출력버퍼 bw에 저장된 메시지들을 한번에 방출(flush)하고
출력버퍼 bw도 종료함으로
프로그램은 마쳐진다.
Buffered I/O는 빠르고 효율적이지만
Scanner보다 예민하기 때문에,
close()로 닫아주는것이 "안전하다."
(throws IOException을 작성한것도 그 이유!!)
그래서 최종적인 코드는 아래와 같다.
import java.io.*;
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;
int T = Integer.parseInt(br.readLine(), " ");
for(int i=0; i<T; i++){
st = new StringTokenizer(br.readLine(), " ");
bw.write((Integer.parseInt(st.nextToken()) + Integer.parseInt(st.nextToken())) + "\n");
}
br.close();
bw.flush();
bw.close();
}
}
맞았습니다!!