본문으로 바로가기
제품데스크톱 도구TASTECAD도면 확인TASTEFILES파일 관리TASTEFTP파일 전송TASTESSH원격 작업공간TASTEZIP압축과 해제개발 도구TASTECODERust 통합 개발 환경TASTESTUDIO통합 개발·테스트 환경TASTEETL데이터 통합(ETL)서버TASTEREMOTE원격 데스크톱 서버TASTEGEO공간정보 서버TASTEMAIL메일 작업공간시작하기다운로드문서구매모든 제품
마켓플레이스
소식
개발소식오늘의 개발 소식개발 문서프로그래밍 언어RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDart프런트엔드 프레임워크Next.jsReactVue.js · NuxtSvelteKitAngular서버 프레임워크Spring BootDjangoFastAPIASP.NET CoreNestJS · Express앱 · 데스크톱 프레임워크TauriFlutterReact NativeElectron알고리즘알고리즘 기초알고리즘 핵심알고리즘 심화실무 알고리즘
커뮤니티프로젝트개발 로그프롬프트AI 도구 이슈쇼케이스커뮤니티 안내
협업기술 전수홈페이지 구축데스크톱 앱 구축릴리스·결제 파이프라인판매 파트너문의
서비스원격 데스크톱설치 패키지 커스텀
TASTEDEV
제품

데스크톱 도구

TASTECAD복잡한 도면을 가볍게 열다TASTEFILES필요한 파일만, 가장 빠르게TASTEFTP파일이 오가는 가장 단정한 길TASTESSH서버와 나 사이, 더 단단한 연결TASTEZIP더 빠르게 묶고, 더 안전하게 풀다

개발 도구

TASTECODERust 앱을 편집 · 빌드 · 디버깅 · 테스트까지 한 창에서TASTESTUDIO편집부터 원격 테스트와 승인 기반 AI 수정까지TASTEETL값을 보며 데이터를 옮깁니다

서버

TASTEREMOTE우리 회사 서버로 운영하는 원격 데스크톱TASTEGEOGeoServer 호환 공간정보 서버를 Rust로 다시 세웁니다TASTEMAIL메일의 주도권을 다시 내 손에

시작하기

다운로드모든 제품 최신 판문서제품 사용법구매구독 · 영구 라이선스모든 제품모든 제품 한눈에
모든 제품
마켓플레이스소식
개발

소식

오늘의 개발 소식언어 · 프레임워크 · GitHub · AI 공식 발표개발 문서언어 · 프레임워크 · 알고리즘 안내서

프로그래밍 언어

RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDart

프레임워크

프런트엔드 프레임워크Next.jsReactVue.js · NuxtSvelteKitAngular
서버 프레임워크Spring BootDjangoFastAPIASP.NET CoreNestJS · Express
앱 · 데스크톱 프레임워크TauriFlutterReact NativeElectron

알고리즘

알고리즘 기초복잡도 분석 · 정렬 · 탐색 · 기본 자료구조 · 트리와 힙알고리즘 핵심그래프 탐색 · 최단 경로와 최소 신장 트리 · 동적 계획법 · 탐욕 알고리즘 · 분할 정복 · 백트래킹알고리즘 심화문자열 알고리즘 · 수학과 정수론 · 비트 연산 · 구간 트리 · 유니온 파인드실무 알고리즘코딩 면접 풀이 전략 · LRU 캐시 · 레이트 리미터 · 일관된 해시
개발 문서 전체 보기
커뮤니티
프로젝트빌더와 작업 발견개발 로그결정과 시행착오프롬프트재사용 가능한 지시AI 도구 이슈Claude · Codex · Gemini 문제와 우회법쇼케이스완성된 결과커뮤니티 안내공개하고 함께 만드는 방식
협업
기술 전수Rust·egui 네이티브 앱 만들기홈페이지 구축10개 언어, 계정, 문서·다운로드데스크톱 앱 구축Rust·egui, WebView 없이릴리스·결제 파이프라인서명 · MSI·deb·rpm·AppImage · 해시판매 파트너소개하고 결제액의 30% 받기문의구축 · 제휴 · 투자 문의
서비스
원격 데스크톱브라우저로 내 컴퓨터에 접속설치 패키지 커스텀필요한 기능만, 설정은 미리
구매
KO
한국어EnglishDeutschEspañolFrançaisItalianoPortuguês (Brasil)日本語简体中文繁體中文
로그인
로그인
TASTEDEV

작은 도구부터, 더 좋은 개발까지.

support@tastedev.netTASTEDEV 후원하기
제품제품군구매문서다운로드마켓플레이스고객 지원
커뮤니티프로젝트개발 로그프롬프트AI 도구 이슈쇼케이스
정책개인정보처리방침이용약관구독 약관환불 정책커뮤니티 운영 정책
계정로그인가입하기
방문자
오늘
012345678901234567890123456789012345678901234567890123456789
어제
012345678901234567890123456789012345678901234567890123456789
누적 조회
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
상호
지엑스소프트
대표자
최영구
사업자등록번호
853-44-00368
주소
인천광역시 미추홀구 경인로 351 9층 V24
전화
+82-10-4404-1523
이메일
whitecalvin@tastedev.net
개인정보 보호책임자
최영구

© 2026 TASTEDEV제품 정보는 현재 검증된 개발 소스를 기준으로 합니다.출시·고도화 중

복잡도 분석 문서
복잡도 분석
복잡도 분석의 개념동작 원리: 연산 세기에서 마스터 정리까지구현: 세 가지 차수를 직접 재 보기복잡도: 대표 차수, 상환 분석, 공간연습 문제실무 활용
토론

복잡도 분석 안내서 · 1/6

복잡도 분석의 개념

복잡도 분석은 알고리즘이 입력 크기에 따라 시간과 메모리를 얼마나 더 쓰는지를 따지는 방법입니다. "이 코드는 0.3초 걸린다"는 측정값은 컴퓨터, 언어, 입력 데이터에 따라 달라지지만, "입력이 두 배가 되면 실행 시간이 네 배가 된다"는 성질은 어느 환경에서나 거의 그대로 유지됩니다. 복잡도 분석은 바로 이 성장의 모양을 다룹니다. 이 장에서는 입력 크기, 점근 표기(O, Ω, Θ), 최선·평균·최악의 경우, 그리고 앞으로 계속 쓰게 될 용어를 정리합니다.

입력 크기 n

분석은 입력 크기를 정하는 데서 시작합니다. 리스트라면 원소 수, 문자열이라면 길이가 보통 n입니다. 그래프처럼 정점 수 V와 간선 수 E 두 변수를 함께 써야 하는 경우도 있고, 두 문자열을 비교하는 문제라면 각 길이 m과 n을 따로 둡니다.

정수 하나를 입력으로 받는 함수는 조심해야 합니다. 입력 크기는 값 자체가 아니라 그 수를 적는 데 필요한 자릿수(비트 수)입니다. 그래서 2부터 √n까지 나눠 보는 소수 판별은 값 n에 대해서는 O(√n)이지만, 비트 수 b에 대해서는 O(2^(b/2))인 지수 시간입니다.

점근 표기: O, Ω, Θ

점근 표기는 n이 충분히 커졌을 때 함수가 자라는 속도를 비교하는 말입니다.

  • Big-O(상한): 어떤 양의 상수 c와 시작점 n0이 있어서 n ≥ n0인 모든 n에 대해 f(n) ≤ c·g(n)이면 f(n) = O(g(n))이라고 씁니다. "g보다 빠르게 자라지 않는다"는 뜻입니다.
  • Big-Omega(하한): 같은 조건에서 f(n) ≥ c·g(n)이면 f(n) = Ω(g(n))입니다. "적어도 g만큼은 자란다"는 뜻입니다.
  • Big-Theta(딱 맞는 차수): O와 Ω를 모두 만족하면 f(n) = Θ(g(n))입니다. 성장 속도가 g와 같은 차수라는 뜻입니다.

예를 들어 f(n) = 3n² + 5n + 20은 n ≥ 1에서 3n² ≤ f(n) ≤ 28n²이므로 Θ(n²)입니다. O(n³)이라고 써도 틀리지는 않지만 느슨한 상한이라 정보가 적습니다. 실무에서 "이 함수는 O(n²)이다"라고 말할 때는 대개 Θ의 뜻으로 씁니다.

상수와 낮은 차수 항을 버리는 이유는 n이 커질수록 가장 높은 차수 항이 전체를 좌우하기 때문입니다. 아래 코드로 비율을 직접 확인할 수 있습니다.

def f(n):
    return 3 * n * n + 5 * n + 20

for n in (10, 100, 1_000, 10_000):
    print(n, f(n), round(f(n) / (n * n), 4))
# 10 370 3.7
# 100 30520 3.052
# 1000 3005020 3.005
# 10000 300050020 3.0005

비율이 상수 3으로 다가갑니다. 즉 f는 결국 n²의 상수배처럼 움직이고, 상수 3은 하드웨어나 구현에 따라 바뀌는 값이므로 표기에서 뺍니다.

경우와 한계는 다른 축입니다

흔한 오해는 "O는 최악의 경우, Ω는 최선의 경우"라는 생각입니다. 실제로는 두 가지가 서로 다른 질문입니다.

  • 어떤 입력을 볼 것인가: 최선의 경우, 평균적인 경우, 최악의 경우
  • 그 실행 시간을 어떻게 표현할 것인가: 상한 O, 하한 Ω, 딱 맞는 차수 Θ

선형 탐색은 찾는 값이 맨 앞에 있으면 비교 1번으로 끝나고(최선 Θ(1)), 없거나 맨 끝에 있으면 n번 비교합니다(최악 Θ(n)). 값이 리스트 안에 고르게 있다고 가정하면 평균 비교 횟수는 (n + 1) / 2이고, 이것도 Θ(n)입니다.

def linear_search(items, target):
    comparisons = 0
    for i, x in enumerate(items):
        comparisons += 1
        if x == target:
            return i, comparisons
    return -1, comparisons

data = [7, 3, 9, 4, 1]
print(linear_search(data, 7))   # (0, 1)  최선의 경우
print(linear_search(data, 1))   # (4, 5)  끝에 있는 경우
print(linear_search(data, 8))   # (-1, 5) 없는 경우 = 최악

보통은 최악의 경우를 기준으로 말합니다. 사용자가 어떤 입력을 넣을지 모르므로 "어떤 입력이 와도 이 이상은 걸리지 않는다"는 보장이 가장 쓸모 있기 때문입니다.

시간만이 아니라 공간도

공간 복잡도는 알고리즘이 쓰는 추가 메모리가 입력 크기에 따라 어떻게 자라는지를 봅니다. 입력 자체를 빼고 계산한 것을 보조 공간(auxiliary space)이라고 부릅니다. 같은 문제라도 메모리를 더 써서 시간을 줄이는 선택이 자주 나옵니다.

def has_duplicate_slow(items):      # 시간 O(n²), 보조 공간 O(1)
    for i in range(len(items)):
        for j in range(i + 1, len(items)):
            if items[i] == items[j]:
                return True
    return False

def has_duplicate_fast(items):      # 시간 O(n) 평균, 보조 공간 O(n)
    seen = set()
    for x in items:
        if x in seen:
            return True
        seen.add(x)
    return False

언제 쓰는가

  • 구현하기 전에 여러 방법 가운데 입력 규모에 맞는 것을 고를 때
  • 코딩 테스트에서 제한 시간과 입력 범위를 보고 필요한 차수를 거꾸로 추정할 때
  • 코드 리뷰에서 반복문 안의 in list, 반복되는 정렬처럼 숨은 비용을 찾을 때
  • 데이터가 늘었을 때 서비스가 견딜 수 있는지 미리 가늠할 때

용어 정리

용어뜻
시간 복잡도기본 연산 횟수가 n에 따라 자라는 정도
공간 복잡도추가 메모리가 n에 따라 자라는 정도
점근n이 충분히 커졌을 때의 경향
상환(amortized) 분석여러 연산의 총비용을 연산 수로 나눈 평균 보장
다항 시간O(n^k) 꼴, k는 상수
지수 시간O(2^n)처럼 n이 지수에 있는 꼴

정리

  • 복잡도 분석은 절대 시간이 아니라 입력 크기에 따른 성장의 모양을 봅니다.
  • O는 상한, Ω는 하한, Θ는 둘 다를 뜻하며, 상수와 낮은 차수 항은 버립니다.
  • 최선·평균·최악은 "어떤 입력인가"의 문제이고, O·Ω·Θ와는 다른 축입니다.
  • 시간과 공간은 서로 맞바꿀 수 있으므로 둘을 함께 따져야 합니다.
이 장에 대해 질문이 있나요?
다음 장동작 원리: 연산 세기에서 마스터 정리까지

댓글 0개

인기 댓글순최신순

로그인 · 로그인하면 댓글을 남길 수 있습니다.