프로그램이 얼마나 빠르게 실행되는지를 판단할 때 가장 많이 사용하는 개념이 시간복잡도다. 코드 실행 시간을 직접 재는 대신, 입력 크기(N) 가 커질수록 걸리는 시간이 어떻게 증가하는지를 수학적으로 표현한 것이 시간복잡도다.
가장 많이 쓰는 시간복잡도 표기법이며, 가장 빠르게 증가하는 항만 남기고 나머지는 버린 형태로 표현한다.
| 표기 | 의미 | 예시 |
|---|---|---|
| O(1) | 상수 시간 | 배열에서 인덱스로 값 꺼내기 |
| O(log N) | 로그 시간 | 이진 탐색 |
| O(N) | 선형 시간 | for문 한 번 |
| O(N log N) | 로그 곱 | 정렬 알고리즘(퀵/합병/힙) |
| O(N²) | 제곱 | 이중 for문 |
| O(2ⁿ) | 지수 | 부분집합, 백트래킹 |
| O(N!) | 팩토리얼 | 순열 생성 |
입력 크기와 상관없이 항상 일정한 시간.
int x = arr[5]; // 배열 인덱싱
입력 크기만큼 작업 반복.
for (int i = 0; i < N; i++) { ... }
N이 커질수록 작업량이 기하급수적으로 증가.
이중 반복문이 대표적.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) { ... }
}
전체 범위를 절반씩 줄여가며 탐색.
이진 탐색(Binary Search) 등이 여기에 해당.
정렬 알고리즘에서 자주 등장하며, 효율적인 알고리즘의 기준값으로 여겨진다.
전체 시간에서 가장 큰 영향을 미치는 부분만 고려한다.
예: O(2N) → O(N)
예: O(N² + N) → O(N²)
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cout << i << j << endl;
}
}
반복 횟수: N × N = N²
시간복잡도: O(N²)
int x = N;
while (x > 1) {
x /= 2;
}
반복 횟수: log₂(N)
시간복잡도: O(log N)