알고리즘 문제풀이/C++
[백준/C++] 1920번: 수 찾기 - 시간 초과를 피하는 자료구조와 입출력 최적화
aerimi-code
2026. 2. 12. 16:13
1. 문제 정보
- 문제 번호: 1920번
- 문제 이름: 수 찾기
- 문제 링크: https://www.acmicpc.net/problem/1920
- 문제 요약:
- N개의 정수가 주어졌을 때, 이후에 주어지는 M개의 정수들이 기존 N개의 정수 안에 존재하는지 확인하는 프로그램을 작성하시오. (존재하면 1, 없으면 0 출력)
2. 접근 방법 (알고리즘)
❌ 첫 번째 시도: Vector + std::find (시간 초과)
가장 단순하게 vector에 값을 저장하고 find 함수로 하나씩 찾는 방식을 선택했다.
- 문제점: std::find는 벡터의 처음부터 끝까지 확인하는 선형 탐색이다.
- 시간 복잡도: 입력 N, 쿼리 M일 때 O(N X M).
- 결과: N, M이 최대 10만일 경우 연산 횟수가 100억 번에 달해 시간 초과가 발생.
❌ 두 번째 시도: std::set 사용 (여전히 시간 초과?)
탐색 속도를 높이기 위해 내부적으로 이진 탐색 트리(Red-Black Tree) 구조를 가지는 set을 사용.
- 성능: 탐색 속도가 O(log N)으로 빨라짐. 전체 복잡도는 O(M log N).
- 결과: 하지만 여전히 백준에서는 시간 초과가 발생했습니다. 로직의 문제가 아니라 입출력 속도가 문제!
✅ 최종 접근: set + 입출력 최적화 (성공)
C++의 기본 cin/cout은 매우 느리다.
최적화 하는 코드가 필요!
3. 코드 구현 (정답)
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
int main() {
// [최적화 1] C의 stdio와 C++의 iostream 동기화 해제
ios::sync_with_stdio(false);
// [최적화 2] cin과 cout의 묶음을 해제 (불필요한 flush 방지)
cin.tie(nullptr);
int n, m;
set<int> numbers;
// N개의 숫자 입력 및 삽입
cin >> n;
for(int i = 0; i < n; i++) {
int num;
cin >> num;
numbers.insert(num);
}
// M개의 숫자 탐색
cin >> m;
for(int i = 0; i < m; i++) {
int num;
cin >> num;
// set의 find 함수는 O(log N)의 속도를 보장함
if(numbers.find(num) != numbers.end()) {
cout << "1\n";
} else {
cout << "0\n";
}
}
return 0;
}
4. 배운 점 & 회고 (TIL) ✍️
① 탐색 알고리즘의 시간 복잡도
- vector + find: 순차적으로 다 뒤져야 한다. O(N)
- set (Red-Black Tree): 데이터를 넣을 때부터 정렬하며 들어가기 때문에 반씩 나눠서 찾는 이진 탐색 기법을 써서 빠르다.
② C++ 입출력 최적화 비법
로직이 완벽해도 입출력 양이 많으면(보통 10만 건 이상) 아래 두 줄이 필수.
1) ios::sync_with_stdio(false);
- 의미: C++의 iostream과 C의 stdio 사이의 동기화를 끊습니다.
- 효과: 입출력 속도가 비약적으로 향상됩니다.
- 주의: 이제 scanf/printf와 cin/cout을 섞어 쓰면 출력 순서가 꼬일 수 있으므로 하나만 써야 합니다.
2) cin.tie(nullptr);
- 의미: cin과 cout의 결합을 해제합니다.
- 효과: 원래는 입력받기 전에 cout의 버퍼를 비우는(flush) 작업이 자동으로 일어나는데, 이를 막아 시간을 절약합니다. endl 대신 \n을 쓰는 것도 같은 이유입니다.
💡 추가 팁
사실 이 문제에서 더 빠른 성능을 원한다면 set보다 unordered_set을 사용하는 것이 좋다. set은 정렬을 유지하지만, unordered_set은 해시 테이블을 사용하여 탐색 시간이 평균 $O(1)이기 때문입니다.
이번 기회를 통해 알고리즘 문제 해결에는 로직만큼이나 데이터 양에 따른 입출력 환경 최적화가 얼마나 중요한지 깊이 깨달았습니다!