C++로 알고리즘 문제를 풀 때 시간 초과가 나는 경우 시간 복잡도 문제인 경우도 있지만 입출력 관련 코드 때문에 시간 초과가 나는 경우도 많다. 이런 경우 어떠한 방식으로 해결할 수 있는지 정리
1. endl 대신 "\n"
endl
은 개행 문자를 출력하고 버퍼를 비웁니다. 버퍼를 비우는 작업은 I/O
작업이 많아 성능 저하를 초래할 수 있습니다.
그에 반해 \n
을 사용하면 버퍼를 비우지 않고 개행만 출력하므로 endl
에 비해 속도가 빠릅니다.
2. ios::sync_with_stdio(false);
기본적으로, C++ 표준 라이브러리는 C 표준 라이브러리인 stdio
와 입출력 버퍼를 동기화하여 C 스타일 입출력 함수(printf
, scanf
등)와
C++ 스타일 입출력 함수(cout
, cin
등)를 혼합하여 사용할 수 있습니다. 이는 입출력 동작의 일관성을 유지하지만, 조금 느린 입출력 속도를 가집니다.
ios::sync_with_stdio(false)
는 C++ 표준 라이브러리에서 입출력 동기화를 해제하는 역할을 합니다. ios::sync_with_stdio(false)
호출 시
stdio
라이브러리와 분리되었기 때문에 C++의 cin, cout과 C의 printf, scanf 등을 같이 사용하면 안됩니다.
3. cin.tie(NULL); cout.tie(NULL):
cin.tie(NULL)
코드는 cin
과 cout
의 묶음을 해제하는 코드입니다.
기본적으로 C++은 cin
으로 읽을 때 먼저 출력 버퍼를 비웁니다. 아래 코드를 예시로 들면, C++에서는 기본적으로
변수를 cin
으로 입력받기 전에 cout
으로 문장 출력을 먼저합니다.
std::cout << "Enter name:";
std::cin >> name;
입력과 출력이 번갈아가며 수 많이 반복하는 알고리즘 문제에서는 출력이 먼저 되는게 중요하지 않으므로 cin.tie(NULL);
코드를 추가하여
cout
과 cin
의 묶음을 해제하여 실행 속도를 향상시킬 수 있습니다.
cout.tie(NULL)
은 cout
을 표준 출력 버퍼와 묶지 않도록 설정하는 코드인데 cin.tie(NULL)
에 비해 실행 시간에 크게 영향을 미치지 않는다고 합니다.
자세한 건 아래 출력 속도 비교 링크에서 확인 가능합니다.
위 세 가지 방식은 C++로 알고리즘 문제풀 때 실행 시간을 줄이기 위해 많이 사용하는 방식입니다.
그러나 출력 속도 비교와
입력 속도 비교 링크를 보시면
다양한 언어에서 입출력 속도를 향상시키는 코드를 테스트한 결과가 있는데 cout.tie(NULL)
는 출력 속도 향상에 거의 영향을 미치지 않는다고 합니다.
그에 반해 \n
사용과 cin.tie(NULL)
그리고 ios::sync_with_stdio(false)
는 속도 향상에 긍정적인 영향을 미치는 것을 확인할 수 있습니다.