Skip to content

Commit cd066f6

Browse files
committed
feat: add combination-sum solution
1 parent 31235d2 commit cd066f6

File tree

1 file changed

+150
-3
lines changed

1 file changed

+150
-3
lines changed

combination-sum/shinsj4653.py

+150-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,160 @@
11
"""
22
[문제풀이]
33
# Inputs
4-
4+
서로 다른 정수 배열 candidates
5+
타겟 정수 target
56
# Outputs
6-
7+
서로 다른 숫자 조합들(리스트) 담은 리스트
78
# 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
814
915
# 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+
정답 참고
1049
1150
[회고]
1251
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

Comments
 (0)