[C++] 알고리즘 시간 초과

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)코드는 cincout의 묶음을 해제하는 코드입니다.

기본적으로 C++은 cin으로 읽을 때 먼저 출력 버퍼를 비웁니다. 아래 코드를 예시로 들면, C++에서는 기본적으로 변수를 cin으로 입력받기 전에 cout으로 문장 출력을 먼저합니다.

std::cout << "Enter name:";
std::cin >> name;

입력과 출력이 번갈아가며 수 많이 반복하는 알고리즘 문제에서는 출력이 먼저 되는게 중요하지 않으므로 cin.tie(NULL); 코드를 추가하여 coutcin의 묶음을 해제하여 실행 속도를 향상시킬 수 있습니다.

cout.tie(NULL)cout을 표준 출력 버퍼와 묶지 않도록 설정하는 코드인데 cin.tie(NULL)에 비해 실행 시간에 크게 영향을 미치지 않는다고 합니다. 자세한 건 아래 출력 속도 비교 링크에서 확인 가능합니다.


위 세 가지 방식은 C++로 알고리즘 문제풀 때 실행 시간을 줄이기 위해 많이 사용하는 방식입니다.

그러나 출력 속도 비교입력 속도 비교 링크를 보시면 다양한 언어에서 입출력 속도를 향상시키는 코드를 테스트한 결과가 있는데 cout.tie(NULL)는 출력 속도 향상에 거의 영향을 미치지 않는다고 합니다.

그에 반해 \n사용과 cin.tie(NULL) 그리고 ios::sync_with_stdio(false)는 속도 향상에 긍정적인 영향을 미치는 것을 확인할 수 있습니다.