가능한 답이 백 개라면 백 개를 다 확인하면 됩니다. 백만 개라면 그럴 수 없습니다.
완전탐색은 실패한 방법이 아닙니다
모든 경우를 나열해서 확인하는 방법을 완전탐색(brute force) 이라고 합니다. 흔히 마지막 수단처럼 취급되지만, 실제로는 기준선입니다.
두 가지 이유에서 그렇습니다. 완전탐색은 정확합니다. 모든 경우를 봤으니 답을 놓칠 수 없습니다. 그리고 완전탐색은 문제를 정의하는 일이기도 합니다. 무엇이 경우이고 무엇이 조건인지 나열해봐야 문제의 구조가 드러납니다.
자료구조 시리즈 ep.01 크기가 접근법을 정한다에서 본 대응표는 여기서도 그대로 쓰입니다. 경우의 수를 계산하면 완전탐색이 통과할지 아닐지 바로 나옵니다. 원소 20개의 부분집합은 2²⁰, 약 백만 개라 통과하고, 40개면 2⁴⁰, 약 1조 개라 통과하지 못합니다. 통과하면 그대로 씁니다. 더 영리한 방법을 찾을 이유가 없습니다.
실무에서도 완전탐색을 그대로 쓰는 경우가 있습니다. 화면의 권한 조합이 스무 가지 이하라면 모든 조합을 실제로 그려 확인하는 테스트를 돌릴 수 있고, 설정 값의 가짓수가 적으면 조합을 전부 넣어보는 편이 규칙을 따로 만드는 것보다 안전합니다.
통과하지 못하면 무엇을 안 봐도 되는지 물어야 합니다.
줄이는 근거는 네 가지입니다
탐색 공간을 줄이려면 근거가 필요합니다. 근거 없이 줄이면 답을 놓칩니다. 알고리즘 시리즈에서 다루는 방법들은 이 근거를 기준으로 묶었습니다.
구조를 이용합니다. 데이터에 연결 관계가 있으면 아무 순서로나 훑을 이유가 없습니다. 이어진 것만 따라가면 됩니다. 그래프 탐색이 여기 속합니다.
단조성을 이용합니다. 어떤 기준으로 정렬했을 때 한 방향으로만 조건이 바뀐다면, 절반을 확인하지 않고 버릴 수 있습니다. 이분탐색과 투 포인터가 이 근거로 움직입니다.
국소 최적이 전체 최적이 되는 조건을 이용합니다. 매번 눈앞에서 가장 좋은 선택을 했을 때 그것이 전체 답이 되는 문제가 있습니다. 여기서 그리디가 성립합니다.
계산 결과를 재사용합니다. 같은 부분 문제가 여러 번 나온다면 한 번만 계산하고 기억해둡니다. 동적 계획법입니다.
네 근거는 실무에서도 그대로 만납니다. 파일 시스템을 훑거나 패키지 의존성을 따라갈 때는 구조를 이용하고, 정렬된 로그에서 특정 시각을 찾을 때는 단조성을 이용합니다. 남은 작업을 짧은 것부터 배치하는 스케줄러는 국소 최적을, 같은 요청의 응답을 캐시하는 서버는 재사용을 이용합니다.
알고리즘 시리즈에서 다루는 것
2부인 알고리즘 시리즈는 이 편을 제외하고 여섯 편입니다.
- ep.01 문제를 그래프로 바꿔 보기: 그래프 탐색을 알아봅니다. 문제를 그래프로 바꿔 보는 시각을 먼저 잡고, 깊이 우선과 너비 우선이 어떻게 다른 질문에 답하는지 봅니다. 격자를 그래프로 읽는 방법도 여기서 다룹니다.
- ep.02 탐색 공간을 줄이는 근거: 이분탐색의 전제인 단조성, 답 자체를 이분탐색하는 파라메트릭 서치, 투 포인터, 백트래킹의 가지치기, 비트마스킹을 하나의 관점으로 묶습니다.
- ep.03 언제 욕심내고 언제 기억하는가: 그리디와 동적 계획법을 알아봅니다. 두 방법의 경계에 무엇이 있는지, 그리디가 깨지는 신호를 어떻게 알아채는지가 중심입니다.
- ep.04 가중치와 순서와 연결성: 그래프 심화를 알아봅니다. 간선에 가중치가 붙거나, 순서 제약이 있거나, 연결 여부만 알면 되는 상황에서 각각 어떤 도구를 쓰는지 정리합니다.
- ep.05 문자열 안에서 패턴 찾기: 문자열 매칭을 알아봅니다. 이중 반복문보다 빠를 수 있는 이유를 KMP의 실패 함수로 설명하고, 접두사를 공유하는 트라이까지 봅니다.
- ep.06 정수를 다루는 도구들: 최대공약수와 소수 판별, 모듈러 연산처럼 문제 안에 조용히 섞여 들어오는 계산들을 모았습니다.
읽는 순서
각 편은 독립된 질문 하나에 답합니다. 순서대로 읽지 않아도 괜찮습니다.
| 편 | 선행 | 강도 |
|---|---|---|
| ep.01 | 자료구조 시리즈 ep.01 | 권장 |
| ep.02 | 자료구조 시리즈 ep.01 | 권장 |
| ep.03 | ep.02 | 권장 |
| ep.04 | ep.01 | 필수 |
| ep.04 | 자료구조 시리즈 ep.04 | 권장 |
| ep.05 | 없음 | 독립 |
| ep.06 | 없음 | 독립 |
ep.04만 그래프 표현과 탐색을 전제로 하므로 ep.01을 먼저 보는 편이 낫습니다. 우선순위 큐를 쓰는 부분은 자료구조 시리즈 ep.04 트리의 모양이 성능을 만든다에 구현이 있습니다.
ep.05와 ep.06은 바로 열어도 됩니다.
참고 자료
- Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009). Introduction to Algorithms (3rd ed.). MIT Press.
- Kleinberg, J., & Tardos, É. (2005). Algorithm Design. Addison-Wesley.
전체 목차
자료구조 시리즈
- ep.00 - 이미 쓰고 있는 것들의 이름
- ep.01 - 크기가 접근법을 정한다
- ep.02 - 배열과 해시의 진짜 비용
- ep.03 - 내장 정렬이 보장하는 것
- ep.04 - 트리의 모양이 성능을 만든다
- ep.05 - 같은 구간을 반복해 묻는다면
알고리즘 시리즈
- ep.00 - 전부 해보는 것과 그러지 않는 것
- ep.01 - 문제를 그래프로 바꿔 보기
- ep.02 - 탐색 공간을 줄이는 근거
- ep.03 - 언제 욕심내고 언제 기억하는가
- ep.04 - 가중치와 순서와 연결성
- ep.05 - 문자열 안에서 패턴 찾기
- ep.06 - 정수를 다루는 도구들
다음 편 예고
그래프는 특수한 자료구조가 아니고, 관계가 있는 모든 데이터가 그래프입니다. 그 시각으로 문제를 다시 읽는 법과, 깊이 우선과 너비 우선이 서로 다른 질문에 답한다는 사실을 봅니다.