본문으로 바로가기
제품데스크톱 도구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제품 정보는 현재 검증된 개발 소스를 기준으로 합니다.출시·고도화 중

백트래킹 문서
백트래킹
백트래킹의 개념동작 원리구현복잡도연습 문제실무 활용
토론

백트래킹 안내서 · 4/6

복잡도

백트래킹의 시간은 결국 방문한 노드 수 × 노드 하나에서 하는 일입니다. 최악의 경우 상태 공간 트리 전체를 돌기 때문에 대부분 지수 시간이나 계승 시간이 걸리고, 가지치기는 이 상한을 바꾸지 못하지만 실제로 도는 노드 수를 크게 줄입니다. 이 장에서는 대표 문제의 복잡도를 정리하고, 가지치기의 효과를 숫자로 확인한 뒤, 완전 탐색과 동적 계획법(DP)과 비교합니다.

대표 문제의 복잡도

문제노드(또는 해) 수시간추가 공간
부분집합2^nO(n · 2^n)O(n)
순열약 e · n!O(n · n!)O(n)
조합 C(n, k)C(n, k)개 해O(k · C(n, k))O(k)
N-Queens상한 n!O(n!) 이하O(n)
스도쿠(빈 칸 m개)상한 9^mO(9^m) 이하O(m)

시간에 붙은 n이나 k는 해 하나를 복사해 저장하는 비용입니다. 공간은 재귀 깊이와 path만 센 것이고, 결과 목록 자체는 해의 개수만큼 더 필요합니다. 최선의 경우는 문제에 따라 다릅니다. 해를 하나만 찾으면 되는 스도쿠는 첫 가지에서 바로 답이 나오면 빈 칸 수에 비례하는 시간에 끝나지만, 해를 모두 나열해야 하는 문제는 해의 개수 자체가 하한이 됩니다.

가지치기의 효과를 재 보기

N-Queens에서 실제로 방문한 노드 수를 세어, 가지치기 없이 행마다 아무 열이나 놓는 경우(n^n)와 열만 겹치지 않게 하는 경우(n!)와 비교합니다.

def count_nodes(n):
    cols, diag, anti = set(), set(), set()
    visited = 0

    def place(row):
        nonlocal visited
        visited += 1
        if row == n:
            return
        for c in range(n):
            if c in cols or row - c in diag or row + c in anti:
                continue
            cols.add(c); diag.add(row - c); anti.add(row + c)
            place(row + 1)
            cols.remove(c); diag.remove(row - c); anti.remove(row + c)

    place(0)
    return visited

for n in (4, 8, 12):
    print(n, count_nodes(n))
n해의 수방문 노드n!n^n
421724256
8922,05740,32016,777,216
1072435,5393,628,80010,000,000,000
1214,200856,189479,001,600약 8.9조

n = 12에서 방문 노드는 n!의 0.2% 정도입니다. 상한은 같아도 실제 탐색량이 이만큼 달라지기 때문에 백트래킹이 쓸 만한 것입니다.

정렬과 한계값으로 더 자르기

합이 target이 되는 부분집합을 찾을 때 수를 미리 정렬해 두면, 어떤 수가 남은 합보다 크다는 순간 그 뒤의 수는 모두 볼 필요가 없습니다. continue가 아니라 break를 쓸 수 있다는 점이 중요합니다.

def subset_sum(nums, target):
    nums = sorted(nums)
    result, path = [], []

    def dfs(start, remain):
        if remain == 0:
            result.append(path[:])
            return
        for i in range(start, len(nums)):
            if nums[i] > remain:
                break                 # 뒤의 수는 더 크므로 전부 잘라 냄
            path.append(nums[i])
            dfs(i + 1, remain - nums[i])
            path.pop()

    dfs(0, target)
    return result

print(subset_sum([8, 2, 6, 3, 5], 11))  # [[2, 3, 6], [3, 8], [5, 6]]

완전 탐색, DP와의 비교

기법탐색 방식잘 맞는 문제약점
완전 탐색모든 후보를 만든 뒤 검사아주 작은 입력, 검증용잘못된 후보도 끝까지 만든다
백트래킹만들면서 검사, 실패 시 되돌아감해 나열, 제약 충족최악은 여전히 지수 시간
분기 한정백트래킹 + 최적값 상한으로 자르기조합 최적화(배낭, TSP)좋은 한계 함수가 필요
DP겹치는 하위 문제의 답을 저장개수 세기, 최솟값/최댓값해를 모두 나열하기는 어렵다

같은 질문도 무엇을 묻느냐에 따라 답이 달라집니다. 합이 target인 부분집합을 모두 나열하라면 백트래킹이, 있는지만 묻거나 개수를 묻는다면 DP가 O(n · target)으로 훨씬 빠릅니다.

def count_subset_sum(nums, target):
    ways = [1] + [0] * target       # ways[s] = 합이 s인 부분집합 수
    for x in nums:
        for s in range(target, x - 1, -1):
            ways[s] += ways[s - x]
    return ways[target]

print(count_subset_sum([8, 2, 6, 3, 5], 11))  # 3

정리

  • 백트래킹의 상한은 상태 공간 트리의 크기이며, 대개 2^n이나 n! 수준입니다.
  • 가지치기는 상한을 바꾸지 않지만 실제 방문 노드를 몇 자릿수씩 줄입니다.
  • 해를 모두 나열해야 하면 백트래킹, 개수나 최적값만 필요하고 하위 문제가 겹치면 DP를 먼저 검토합니다.
이 장에 대해 질문이 있나요?
이전 장구현다음 장연습 문제

댓글 0개

인기 댓글순최신순

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