OPEN HYPER STEP
← 목록으로 (math)
MATH · 26 / 45
math
CHAPTER 26 / 45
읽기 약 2
FUNCTION

빅오 표기법: 코드 속도의 수학


핵심 개념

O(1)·O(log n)·O(n)·O(n log n)·O(n²)·O(2^n) — 데이터 1만→100만일 때 차이를 코드로 증명.

본문

Big-O = 입력 크기 N에 따른 성장률

📋 코드 (8줄)
O(1)        상수
O(log n)    로그 (이진 탐색)
O(n)        선형 (단순 루프)
O(n log n)  머지/퀵 정렬
O(n²)       이중 루프
O(n³)       삼중 루프
O(2^n)      재귀 피보나치 (메모 X)
O(n!)       순열 모두 시도

시각적 비교

PYTHON📋 코드 (21줄)
import math
import matplotlib.pyplot as plt
import numpy as np

n = np.linspace(1, 30, 100)

plt.figure(figsize=(10, 6))
plt.plot(n, np.ones_like(n),       label='O(1)')
plt.plot(n[1:], np.log2(n[1:]),    label='O(log n)')
plt.plot(n, n,                      label='O(n)')
plt.plot(n[1:], n[1:] * np.log2(n[1:]), label='O(n log n)')
plt.plot(n, n ** 2,                 label='O(n²)')
plt.plot(n, 2 ** n,                 label='O(2^n)')
plt.ylim(0, 1000)
plt.xlabel('N (입력 크기)')
plt.ylabel('연산 횟수')
plt.legend()
plt.grid(True)
plt.title('Big-O 성장률 비교')
plt.show()
# O(2^n)이 가장 빠르게 폭발

데이터 크기별 시간 추정

PYTHON📋 코드 (29줄)
# 1초에 1억 연산 가능 가정

def estimate_time(complexity, n):
    operations = {
        'O(1)': lambda x: 1,
        'O(log n)': lambda x: math.log2(x) if x > 0 else 0,
        'O(n)': lambda x: x,
        'O(n log n)': lambda x: x * math.log2(x) if x > 0 else 0,
        'O(n²)': lambda x: x * x,
        'O(2^n)': lambda x: 2 ** min(x, 60),  # 큰 수 방지
    }[complexity](n)
    seconds = operations / 100_000_000
    if seconds < 1: return f"{seconds*1000:.2f}ms"
    if seconds < 60: return f"{seconds:.1f}초"
    if seconds < 3600: return f"{seconds/60:.1f}분"
    if seconds < 86400: return f"{seconds/3600:.1f}시간"
    return f"{seconds/86400:.0f}일"


print(f"{'N':>10} {'O(n)':>10} {'O(n log n)':>15} {'O(n²)':>15} {'O(2^n)':>15}")
for n in [10, 100, 1_000, 10_000, 100_000, 1_000_000]:
    print(f"{n:>10,} {estimate_time('O(n)', n):>10} "
          f"{estimate_time('O(n log n)', n):>15} "
          f"{estimate_time('O(n²)', n):>15} "
          f"{estimate_time('O(2^n)', min(n, 30)):>15}")

# 결과:
# N=100,000일 때 O(n²) = 100억 = 100초+
# N=30일 때 O(2^n) = 10초+

코드별 Big-O 측정

PYTHON📋 코드 (32줄)
import time

def measure(fn, *args):
    t0 = time.perf_counter()
    fn(*args)
    return time.perf_counter() - t0


# O(n) — 단일 루프
def linear(arr):
    return sum(arr)

# O(n²) — 중첩 루프
def quadratic(arr):
    pairs = []
    for i in arr:
        for j in arr:
            pairs.append((i, j))
    return pairs

# O(n log n) — 정렬
def n_log_n(arr):
    return sorted(arr)


# 데이터 크기별 시간 비교
for size in [100, 1000, 10_000]:
    arr = list(range(size))
    t1 = measure(linear, arr)
    t2 = measure(quadratic, arr)
    t3 = measure(n_log_n, arr)
    print(f"N={size:>6} | O(n): {t1*1000:.3f}ms | O(n²): {t2*1000:.3f}ms | O(n log n): {t3*1000:.3f}ms")

Big-O 분석 — 실전 패턴

PYTHON📋 코드 (56줄)
# 패턴 1: 단일 루프 → O(n)
def find_max(arr):
    m = arr[0]
    for x in arr[1:]:
        if x > m:
            m = x
    return m


# 패턴 2: 중첩 루프 → O(n²)
def has_duplicates_v1(arr):
    for i, a in enumerate(arr):
        for j, b in enumerate(arr):
            if i != j and a == b:
                return True
    return False


# 패턴 2 개선: O(n) — 해시셋
def has_duplicates_v2(arr):
    seen = set()
    for x in arr:
        if x in seen:
            return True
        seen.add(x)
    return False


# 패턴 3: 절반씩 줄이기 → O(log n)
def binary_search(arr, target):
    lo, hi = 0, len(arr) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if arr[mid] == target: return mid
        if arr[mid] < target: lo = mid + 1
        else: hi = mid - 1
    return -1


# 패턴 4: 분할 정복 → O(n log n)
def merge_sort(arr):
    if len(arr) <= 1: return arr
    mid = len(arr) // 2
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])
    return merge(left, right)

def merge(a, b):
    result = []
    i, j = 0, 0
    while i < len(a) and j < len(b):
        if a[i] < b[j]:
            result.append(a[i]); i += 1
        else:
            result.append(b[j]); j += 1
    return result + a[i:] + b[j:]

최악 vs 평균 vs 최선

📋 코드 (10줄)
빠른정렬 (Quicksort):
- 최선: O(n log n) — 균등 분할
- 평균: O(n log n)
- 최악: O(n²) — 이미 정렬된 입력

해시 검색:
- 평균: O(1)
- 최악: O(n) — 모든 키가 한 버킷

→ Big-O는 보통 최악을 의미. 실전은 평균도 봐야 함.

다음 챕터

CH.27 "공간 복잡도" — 시간만 빠르면 끝이 아니라 메모리도 중요.


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 알고리즘 코드 10개의 Big-O를
분석해서 가장 느린 것 Top 3와
N별 예상 시간을 보고해줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

한국 코딩 테스트에서 시간초과로
떨어지는 사례 Top 10과 각각의
복잡도 개선 패턴을 알려줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 코드베이스의 모든 함수에서
중첩 루프 + 리스트 in 검사 위치를
자동 분석해서 우선 개선안을 만들어줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 시니어 면접에서 Big-O 질문
출제 빈도와 깊이를 한국 IT 대기업 기준으로
솔직히 알려줘.

⭐ 이것만 기억하세요
빅오 표기법: 코드 속도의 수학 이 3가지만 확실히 잡으세요
1.Big-O는 입력 크기 N에 따른 성장률 — 상수 무시, 최고차항만 보존 (O(2n+5) → O(n))
2.O(n²) 알고리즘은 N=10만에서 100초+ 걸림 — 데이터 1만 넘으면 O(n log n) 이하 필수
3.다음 챕터 CH.27에서 공간 복잡도 — 시간뿐 아니라 메모리 사용도 분석


공유하기
진행도 26 / 45