Leetcode 39 조합 합

발행: (2025년 12월 18일 오전 01:40 GMT+9)
5 min read
원문: Dev.to

Source: Dev.to

위에 제공된 소스 링크 외에 번역할 텍스트가 없습니다. 번역을 원하는 본문을 제공해 주시면 한국어로 번역해 드리겠습니다.

Problem Statement

서로 다른 정수들로 이루어진 배열 candidates와 목표 정수 target이 주어지면, 선택한 숫자들의 합이 target이 되는 모든 고유 조합을 반환합니다.
각 후보를 무한히 사용할 수 있습니다. 두 조합은 최소 하나의 숫자 빈도가 다르면 서로 다른 것으로 간주합니다.

예시: [2,3,3], [3,2,3], 그리고 [3,3,2]는 동일한 고유 조합을 나타냅니다.

예시

입력

candidates = [2,3,5]
target = 8

출력

[[2,2,2,2], [2,3,3], [3,5]]

수학적 공식화

문제는 다음과 같은 비음수 정수 x, y, z를 찾는 것으로 표현할 수 있다.

2·x + 3·y + 5·z = 8

해결책

class Solution:
    def combinationSum(self, candidates, target):
        results = []

        def backtrack(remain, comb, start):
            if remain == 0:
                # 유효한 조합을 찾음
                results.append(list(comb))   # 얕은 복사
                return
            if remain < 0:
                # 합이 초과되어 이 경로 탐색을 중단
                return

            for i in range(start, len(candidates)):
                # 후보 선택
                comb.append(candidates[i])
                # 같은 시작 인덱스로 계속 탐색 (재사용 허용)
                backtrack(remain - candidates[i], comb, i)
                # 백트래킹
                comb.pop()

        backtrack(target, [], 0)
        return results

일반적인 함정

함정발생 원인해결 방법
results.append(comb)comb이라는 가변 리스트에 대한 참조를 추가합니다; 이후 수정이 저장된 결과를 손상시킵니다.얕은 복사본을 저장하려면 results.append(list(comb))를 사용합니다.
Looping over all candidates each recursion: for i in range(len(candidates))같은 조합의 순열이 허용됩니다(예: [2,3][3,2]).start 인덱스부터 반복합니다: for i in range(start, len(candidates)).
Not handling remain < 0합이 초과된 후 불필요한 재귀 호출이 발생합니다.remain < 0이면 즉시 반환합니다.

깊이‑우선 탐색 워크스루

예제(candidates = [2,3,5], target = 8)에 대한 재귀 트리는 아래와 같이 나타내며(각 노드는 i – 인덱스, v – 값, remain, start를 보여줍니다).

root (target: 8)
└── [i:0, v:2] remain: 6, start: 0
    ├── [i:0, v:2] remain: 4, start: 0
    │   ├── [i:0, v:2] remain: 2, start: 0
    │   │   ├── [i:0, v:2] remain: 0, start: 0 ── Success → [2,2,2,2]
    │   │   ├── [i:1, v:3] remain: -1 ── Fail
    │   │   └── [i:2, v:5] remain: -3 ── Fail
    │   ├── [i:1, v:3] remain: 1, start: 1
    │   │   ├── [i:1, v:3] remain: -2 ── Fail
    │   │   └── [i:2, v:5] remain: -4 ── Fail
    │   └── [i:2, v:5] remain: -1 ── Fail
    ├── [i:1, v:3] remain: 3, start: 1
    │   ├── [i:1, v:3] remain: 0 ── Success → [2,3,3]
    │   └── [i:2, v:5] remain: -2 ── Fail
    └── [i:2, v:5] remain: 1, start: 2
        └── [i:2, v:5] remain: -4 ── Fail
└── [i:1, v:3] remain: 5, start: 1
    ├── [i:1, v:3] remain: 2, start: 1
    │   ├── [i:1, v:3] remain: -1 ── Fail
    │   └── [i:2, v:5] remain: -3 ── Fail
    └── [i:2, v:5] remain: 0 ── Success → [3,5]
└── [i:2, v:5] remain: 3, start: 2
    └── [i:2, v:5] remain: -2 ── Fail

Source:

참조 표

현재 경로남은시작i (인덱스)후보[i]결과
[2]6002계속
[2,2]4002계속
[2,2,2]2002계속
[2,2,2,2]0002성공 (8)
[2,2,2,3]-1013실패
[2,2,2,5]-3025실패
[2,2,3]1013계속
[2,2,3,3]-2113실패
[2,2,3,5]-4125실패
[2,2,5]-1025실패
[2,3]3013계속
[2,3,3]0113성공 (8)
[2,3,5]-2125실패
[2,5]1025계속
[2,5,5]-4225실패
[3]5113계속
[3,3]2113계속
[3,3,3]-1113실패
[3,3,5]-3125실패
[3,5]0125성공 (8)
[5]3225계속
[5,5]-2225실패
Back to Blog

관련 글

더 보기 »

중첩 리스트 평탄화

여러분, 안녕하세요! 👋 요즘 제가 좀 조용했죠. 사실 지난주에 꽤 심한 독감에 걸려서 완전히 쓰러졌어요. 🤒 그게 제가 …