시간·공간 복잡도
시간 복잡도와 공간 복잡도의 의미와 계산 방법, 그리고 두 지표 간의 트레이드오프를 예제로 알아봅니다.
지난 글에서 알고리즘 분석의 개념을 살펴봤습니다. 이번에는 알고리즘 성능을 측정하는 두 축인 시간 복잡도와 공간 복잡도를 더 깊이 파고들겠습니다.
시간 복잡도 (Time Complexity)
시간 복잡도는 입력 크기 n이 증가함에 따라 알고리즘이 수행하는 기본 연산의 횟수가 어떻게 증가하는지를 나타냅니다. 실제 실행 시간(초)이 아니라 연산 횟수의 증가율에 집중합니다.
# O(1): 배열 인덱스 접근 — 항상 1번
def get_first(arr):
return arr[0]
# O(n): 배열 전체 순회 — n번
def find_max(arr):
m = arr[0]
for x in arr: # n번 반복
if x > m:
m = x
return m
# O(n²): 중첩 루프 — n × n번
def has_duplicate(arr):
for i in range(len(arr)):
for j in range(i+1, len(arr)):
if arr[i] == arr[j]:
return True
return False
공간 복잡도 (Space Complexity)
공간 복잡도는 알고리즘이 실행되는 동안 사용하는 추가 메모리(보조 공간)의 양입니다. 입력 데이터가 차지하는 공간은 제외하고, 알고리즘이 자체적으로 필요로 하는 메모리만 계산합니다.
def reverse_in_place(arr):
left, right = 0, len(arr) - 1 # 변수 2개만 사용
while left < right:
arr[left], arr[right] = arr[right], arr[left]
left += 1
right -= 1
# 공간 복잡도: O(1) — 추가 배열 없음
def reverse_copy(arr):
return arr[::-1] # 길이 n의 새 배열 생성
# 공간 복잡도: O(n)
재귀 함수는 스택 프레임을 사용하므로 공간 복잡도에 주의해야 합니다.
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
# 공간 복잡도: O(n) — 깊이 n의 재귀 스택
시간-공간 트레이드오프
시간과 공간은 종종 트레이드오프(trade-off) 관계에 있습니다. 메모리를 더 사용해서 계산 시간을 줄이거나, 반대로 메모리를 아끼고 더 많은 계산을 하는 식입니다.
피보나치 수열이 대표적인 예입니다. 순수 재귀는 O(2ⁿ) 시간이지만 O(n) 메모리, 메모이제이션은 O(n) 시간과 O(n) 메모리, 반복문 방식은 O(n) 시간과 O(1) 메모리로 구현할 수 있습니다.
# 반복문 방식: O(n) 시간, O(1) 공간
def fib_iterative(n):
if n <= 1:
return n
a, b = 0, 1
for _ in range(2, n + 1):
a, b = b, a + b
return b
복잡도 계산 규칙
복잡도를 구할 때 적용하는 핵심 규칙들입니다.
덧셈 규칙: 순차 실행은 각 부분의 최대값
def two_loops(arr):
for x in arr: # O(n)
print(x)
for x in arr: # O(n)
print(x * 2)
# 총 O(n) + O(n) = O(2n) → O(n)
곱셈 규칙: 중첩 실행은 곱
def nested(arr1, arr2):
for x in arr1: # O(n)
for y in arr2: # O(m)
print(x, y)
# 총 O(n × m) = O(nm)
지배 항 선택: 가장 빠르게 증가하는 항만 남김
T(n) = 5n³ + 100n² + 1000n + 9999 → O(n³)
공간 복잡도 주의사항: 입력 공간
보조 공간(auxiliary space)만 따집니다. 입력 배열 자체의 n개 원소는 포함하지 않습니다.
def sum_array(arr): # 입력: n개 원소
total = 0 # 보조: 변수 1개
for x in arr:
total += x
return total
# 공간 복잡도: O(1) — 보조 공간만 계산
정리
| 복잡도 | 시간 | 공간 |
|---|---|---|
| O(1) | 상수 연산 | 고정 변수만 |
| O(log n) | 반씩 줄임 | 재귀 스택 log n |
| O(n) | 1회 순회 | 크기 n 배열 |
| O(n log n) | 분할 정복 | 보조 배열 |
| O(n²) | 중첩 루프 | 2D 배열 |
- 시간·공간은 트레이드오프 관계 — 상황에 맞게 선택
- 복잡도는 지배 항만 남긴다:
O(n² + n)→O(n²) - 재귀는 스택 공간이 있음을 잊지 말 것
지난 글: 알고리즘 분석 입문
다음 글: 빅오 표기법
읽어주셔서 감사합니다. 😊