2 분 소요


단계 제목 설명  
3 반복문 for, while 등의 반복문을 사용해 봅시다.  
  소단계 문제번호 제목
  6 15552 빠른 A + B
    빠르게 입력받고 출력하는 문제  

문제

본격적으로 for문 문제를 풀기 전에 주의해야 할 점이 있다. 입출력 방식이 느리면 여러 줄을 입력받거나 출력할 때 시간초과가 날 수 있다는 점이다.

C++을 사용하고 있고 cin/cout을 사용하고자 한다면, cin.tie(NULL)과 sync_with_stdio(false)를 둘 다 적용해 주고, endl 대신 개행문자(\n)를 쓰자. 단, 이렇게 하면 더 이상 scanf/printf/puts/getchar/putchar 등 C의 입출력 방식을 사용하면 안 된다.

Java를 사용하고 있다면, Scanner와 System.out.println 대신 BufferedReader와 BufferedWriter를 사용할 수 있다. BufferedWriter.flush는 맨 마지막에 한 번만 하면 된다.

Python을 사용하고 있다면, input 대신 sys.stdin.readline을 사용할 수 있다. 단, 이때는 맨 끝의 개행문자까지 같이 입력받기 때문에 문자열을 저장하고 싶을 경우 .rstrip()을 추가로 해 주는 것이 좋다.

또한 입력과 출력 스트림은 별개이므로, 테스트케이스를 전부 입력받아서 저장한 뒤 전부 출력할 필요는 없다. 테스트케이스를 하나 받은 뒤 하나 출력해도 된다.

자세한 설명 및 다른 언어의 경우는 이 글에 설명되어 있다.

이 블로그 글에서 BOJ의 기타 여러 가지 팁을 볼 수 있다.

입력

첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다.

출력

각 테스트케이스마다 A+B를 한 줄에 하나씩 순서대로 출력한다.

내 제출

T = int(input())

for i in range(T):
    a, b = map(int, input().split())
    print(a + b,"\n")

결과

오답: 시간초과

수정 제출

import sys

T = int(input())

for i in range(T):
    a, b = map(int, sys.stdin.readline().split())
    print(a + b)

######

결과

정답

오답 이유

이번문제의 오답은 시간 초과입니다. 즉 빠르게 입력을 받는것이 중요한데, 이때 입력 함수인 input() 보다 sys.stdin.readline() 을 사용하여 반복입력을 받도록 합니다.

이때 stdin.readline() 을 사용할때 sys 를 불러오는과정이 필요하기 때문에, import sys 를 추가후 실행시키도록 합니다.

###

사용된 코드 이론


input()대신 sys.stdin.readline()을 사용하는 이유

한 두줄 입력받는 문제들과 다르게, 반복문으로 여러줄을 입력 받아야 할 때는 input()으로 입력 받는다면 시간초과가 발생할 수 있습니다. 대표적인 예시가 백준 BOJ 15552번 문제입니다.

import sys

T = int(input()) #Test case
for i in range(T):
        a,b = map(int, sys.stdin.readline().split())
        print(a+b)

맨 첫줄 Test case를 입력받을 때는 input()을 사용해도 무방합니다.
그러나 반복문으로 여러줄 입력받는 상황에서는 반드시 sys.stdin.readline()을 사용해야 시간초과가 발생하지 않습니다.

💡 sys.stdin.readline() 사용법

📌한 개의 정수를 입력받을 때

import sys
a = int(sys.stdin.readline())

😨 그냥 a = sys.stdin.readline() 하면 안되나요?
👉 sys.stdin.readline()은 한줄 단위로 입력받기 때문에, 개행문자가 같이 입력 받아집니다.
만약 3을 입력했다면, 3\n 이 저장되기 때문에, 개행문자를 제거해야 합니다.
또한, 변수 타입이 문자열 형태(str)로 저장되기 때문에, 정수로 사용하기 위해서 형변환을 거쳐야 합니다.

📌정해진 개수의 정수를 한줄에 입력받을 때

import sys
a,b,c = map(int,sys.stdin.readline().split())

map()은 반복 가능한 객체(리스트 등)에 대해 각각의 요소들을 지정된 함수로 처리해주는 함수입니다.
위와 같이 사용한다면 a,b,c에 대해 각각 int형으로 형변환을 할 수 있습니다.

📌 임의의 개수의 정수를 한줄에 입력받아 리스트에 저장할 때

import sys
data = list(map(int,sys.stdin.readline().split()))

split()은 문자열을 나눠주는 함수입니다.
괄호 안에 특정 값을 넣어주면 그 값을 기준으로 문자열을 나누고, 아무 값도 넣어주지 않으면 공백(스페이스, 탭, 엔터 등)을 기준으로 나눕니다.

list()는 자료형을 리스트형으로 변환해주는 함수입니다.
map()은 맵 객체를 만들기 때문에, 리스트형으로 바꿔주기 위해서 list()로 감싸주었습니다.

📌 임의의 개수의 정수를 n줄 입력받아 2차원 리스트에 저장할 때

import sys
data = []
n = int(sys.stdin.readline())
for i in range(n):
    data.append(list(map(int,sys.stdin.readline().split())))

이렇게 한다면 각 요소의 길이가 동일한 2차원 리스트도 만들 수 있고,
각각 길이가 다른 2차원 리스트도 입력 받을 수 있습니다.

📌 문자열 n줄을 입력받아 리스트에 저장할 때

import sys
n = int(sys.stdin.readline())
data = [sys.stdin.readline().strip() for i in range(n)]

strip()은 문자열 맨 앞과 맨 끝의 공백문자를 제거합니다.

👉 입력

3
안녕안녕
나는 지수야
헬륨가스 마셨더니 이렇게됐지

👉 출력
['안녕안녕', '나는 지수야', '헬륨가스 마셨더니 이렇게됐지']



참고문헌

https://velog.io/@yeseolee/Python-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%A0%A5-%EC%A0%95%EB%A6%ACsys.stdin.readline