1
1
"""
2
2
[문제풀이]
3
3
# Inputs
4
-
4
+ 서로 다른 정수 배열 candidates
5
+ 타겟 정수 target
5
6
# Outputs
6
-
7
+ 서로 다른 숫자 조합들(리스트) 담은 리스트
7
8
# Constraints
9
+ unique combinations 개수: 150 이하
10
+ 1 <= candidates.length <= 30
11
+ 2 <= candidates[i] <= 40
12
+ All elements of candidates are distinct.
13
+ 1 <= target <= 40
8
14
9
15
# Ideas
16
+ 같은 숫자가 여러번 선택될 수 있음
17
+ [2,3,6,7] -> target = 7
18
+ 몇 개의 숫자로 구성되는지를 기준으로?
19
+ 최소 숫자 : 2, target max : 40 -> 한 조합 당 최대 20개 숫자
20
+
21
+ 한 개로 구성:
22
+ 7
23
+
24
+ 두 개
25
+ 5 2
26
+ 4 3
27
+
28
+ 세 개
29
+ 2 2 3
30
+
31
+
32
+ 2 3 5 -> 8
33
+
34
+ 8 0
35
+ 7 1
36
+ 6 2
37
+ 5 3
38
+ 4 4
39
+
40
+ 1. 한 개인 경우랑 두 개인 경우만 카운트
41
+ 재귀 돌면서 후보에 있다면 그 후보 담은 리스트 반환
42
+ 점점 올라가면서 return 된 리스트들 더해서 반환
43
+
44
+ 근데 구현 방법이 쉽게 떠오르지 않음..
45
+
46
+ 결국 어찌저찌 최종 리스트들이 반환되게끔 구현하긴 했지만, dp의 장점도 못살리고, set으로 tuple중복 없애려는 구현방법도 실패..
47
+
48
+ 정답 참고
10
49
11
50
[회고]
12
51
13
- """
52
+ 다시 풀면서 막힌 포인트
53
+
54
+ 1. 재귀
55
+ → dfs(i, total + num)
56
+
57
+ 나는 dfs(start, sum(nums)) 로 해버렸다
58
+
59
+ - sum 대신 total + num 으로 지금까지의 합을 갱신하면 더 효율적!
60
+ - start를 넣으면 중복 가짓수 발생.. i를 넣어야 중복 없이 카운트 가능
61
+
62
+ ⇒ 재귀 풀 때 어떤 값을 인자값으로 넣어야 하는지를 설정하는게 가장 어려운듯..연습 많이 해야할듯..
63
+
64
+
65
+ 2. DP
66
+ 다시 풀면서 막힌 포인트
67
+
68
+ → dp[num].append(combination + [candidate])
69
+
70
+ 나는 dp[num].append(combination + [num]) 을 해버렸다
71
+
72
+ 따라서, 후보군들로 이뤄진 후보가 아니라,
73
+
74
+ 누적된 합이 적용된 리스트들이 후보로 인식되어 최종 반환 리스트에 들어가졌다.
75
+ 어떤 변수를 어디에 넣어야 할지, 구현 로직(흐름)을 다시 정리! 복습!
76
+ """
77
+
78
+ # 1번째 코드
79
+ # from collections import defaultdict
80
+ #
81
+ #
82
+ # class Solution:
83
+ # def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
84
+ # ret = []
85
+ #
86
+ # if target == 1:
87
+ # return ret
88
+ #
89
+ # elif target == 2:
90
+ # if target in candidates:
91
+ # ret.append([target])
92
+ # return ret
93
+ #
94
+ # dp = defaultdict(set)
95
+ #
96
+ # for num in candidates:
97
+ # if num == target:
98
+ # ret.append([num])
99
+ #
100
+ # candidates = set(candidates)
101
+ #
102
+ # def dfs(num):
103
+ # if num < 2:
104
+ # return
105
+ #
106
+ # if num < 4:
107
+ # if num in candidates:
108
+ # return [num]
109
+ #
110
+ # else:
111
+ # for i in range(2, num // 2 + 1):
112
+ # # dp[num].add(dfs(target - num) + dfs(num))
113
+ # return dfs(num - i) + dfs(i)
114
+ #
115
+ # for num in range(2, target // 2 + 1):
116
+ # print(dfs(target - num) + dfs(num))
117
+ # dp[num].add(tuple(dfs(target - num) + dfs(num)))
118
+ #
119
+ # temp = set()
120
+ # for value in dp.values():
121
+ # print(value)
122
+ # # temp.add(value)
123
+ #
124
+ # for t in temp:
125
+ # ret.append(list(t))
126
+ #
127
+ # return ret
128
+
129
+ # 2번째 코드 : dp 활용
130
+ class Solution :
131
+ def combinationSum (candidates , target ):
132
+ dp = [[] for _ in range (target + 1 )]
133
+ dp [0 ] = [[]]
134
+ for candidate in candidates :
135
+ for num in range (candidate , target + 1 ):
136
+ for combination in dp [num - candidate ]:
137
+ dp [num ].append (combination + [candidate ])
138
+ return dp [target ]
139
+
140
+ combinationSum ([2 , 3 , 5 ], 8 )
141
+
142
+ # 3번째 코드 : 재귀 활용
143
+ class Solution :
144
+ def combinationSum (candidates , target ):
145
+ output , nums = [], []
146
+
147
+ def dfs (start , total ):
148
+ if total > target :
149
+ return
150
+ if total == target :
151
+ return output .append (nums [:])
152
+ for i in range (start , len (candidates )):
153
+ num = candidates [i ]
154
+ nums .append (num )
155
+ dfs (i , total + num )
156
+ nums .pop ()
157
+
158
+ dfs (0 , 0 )
159
+ return output
160
+ combinationSum ([2 , 3 , 5 , 7 ], 7 )
0 commit comments