Skip to content

Commit f62a2c0

Browse files
committed
4. Combination Sum
1 parent dc1b7af commit f62a2c0

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

combination-sum/whewchews.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
function combinationSum(candidates: number[], target: number): number[][] {
2+
/*
3+
* 합이 target이 되는 candidates 경우의 수를 리턴
4+
* cadidates는 고유함
5+
* 합이 target이 되지 않는 경우, 빈배열 리턴
6+
* cadidate을 중복 사용 가능
7+
* 2 <= candidates[i] <= 40
8+
* => candidate이 1인 경우는 없음
9+
* candidates에서 target보다 같거나 작은 값만 filter하고 시작 (target보다 큰 값은 후보군이 될 수 없음)
10+
*
11+
12+
* [2,3,6,7] / 7
13+
*
14+
* []
15+
* [2] / 5
16+
* [2, 2] 3 => X
17+
* [2, 2, 2] 1 => X
18+
* [2, 2, 2, 2] -1 => X
19+
* [2, 2, 2, 3] -2 => X
20+
* [2, 2, 2, 6] -5 => X
21+
* [2, 2, 2, 7] -6 => X
22+
[2, 2, 3] 0 => O
23+
// ...
24+
[2, 3] 2 => X
25+
[2, 3, 2] 0 => O
26+
// ...
27+
[2, 6] -1 => X
28+
// ...
29+
30+
*
31+
* 하나씩 값을 추가하면서 배열의 총합을 target 값과 비교한다
32+
* sum이 target값보다 작으면 계속 다음 값을 추가해준다
33+
* sum이 target과 같으면 결과 값 result 배열에 추가해준다.
34+
* sum이 target보다 넘으면 마지막에 추가한 값을 뺀다.
35+
* 이 과정을 반복하며 배열에서 결과 값을 찾는다.
36+
*
37+
*/
38+
39+
// TC: O(2^N) N = candidates.length
40+
// SC: O(T) T = target
41+
function backtrack(candidates: number[], start:number, total:number){
42+
if(target === total){
43+
result.push([...path])
44+
return
45+
}
46+
47+
if(target < total){
48+
return
49+
}
50+
51+
for(let i=start; i<=candidates.length-1; i++){
52+
path.push(candidates[i])
53+
backtrack(candidates, i,total + candidates[i])
54+
path.pop()
55+
}
56+
}
57+
58+
const result = []
59+
const path = []
60+
// TC: O(NlogN)
61+
// SC: O(N)
62+
const filteredCandidates = candidates.filter(candidate => candidate<=target).sort((a,b)=> a-b)
63+
backtrack(filteredCandidates, 0, 0)
64+
return result
65+
66+
};
67+
// TC: O(2^N)
68+
// SC: O(2^N)
69+
70+
/* #Solution 2 : DP
71+
* candidates을 가지고 target 값을 만들 있는 모든 조합을 미리 찾아둔다.
72+
*candidates [2,3,6,7] / target 7 라고 했을때
73+
* 1) candidate = 2
74+
* dp[2] = [[2]]
75+
* dp[4] = [[2,2]]
76+
* dp[6] = [[2,2,2]]
77+
* 2) candidate = 3
78+
* dp[3] = [[3]]
79+
* dp[5] = [[2,3]]
80+
* dp[6] = [[2,2,2], [3,3]]
81+
* dp[7] = [[2,2,3]]
82+
* 3) candidate = 6
83+
* dp[6] = [[[2,2,2], [3,3], [6]]
84+
* 4) candidate = 7
85+
* dp[7] = [[2,2,3], [7]]
86+
*
87+
* => dp = [
88+
* [ [] ]
89+
* [ [] ]
90+
* [ [2] ]
91+
* [[3]]
92+
* [[2,2]]
93+
* [[2,3,]]
94+
* [[2,2,2], [3,3], [6]]
95+
* [[2,2,3], [7]]
96+
* ]
97+
* ]
98+
* /
99+
100+
101+
102+
// SC: O(T+1) T = target
103+
const dp = Array.from({ length: target + 1 }, () => []);
104+
dp[0] = [[]];
105+
106+
107+
// TC: O(C), C = candidates.length
108+
for (let candidate of candidates) {
109+
// TC: O(T) T = target
110+
for (let i = candidate; i <= target; i++) {
111+
// TC: O(K) K = dp[i - candidate].length
112+
// SC: O(K)
113+
for (let combination of dp[i - candidate]) {
114+
dp[i].push([...combination, candidate]);
115+
}
116+
}
117+
}
118+
119+
return dp[target];
120+
}
121+
122+
// TC: O(C * T * K)
123+
// SC: O((T+1) * K* T)

0 commit comments

Comments
 (0)