1+ import java .util .ArrayList ;
2+ import java .util .HashSet ;
3+ import java .util .List ;
4+ import java .util .Set ;
5+
6+ /**
7+ * 1번째 풀이는 2번째 풀이를 개선한 것.
8+ * 2번째 풀이는 dfs를 이욯해서 중복순열의 경우의 수를 찾기 때문에 시간복잡도가 매우 높다.
9+ * 또한 중복순열에서 중복을 제거하면서도 낭비되는 연산이 매우 많다.
10+ *
11+ */
12+ class Solution {
13+
14+ /**
15+ * candidates의 후보들은 중복 사용이 가능하다.
16+ * 모든 후보는 구별된다.=> 중복이 없다.
17+ *
18+ * Runtime: 48 ms (Beats 5.56%)
19+ * Memory: 46.96 MB (Beats 6.1%)
20+ * Space Complexity: O(N) + O(K)
21+ * - 사용되는 후보를 Set으로 관리하기 => O(N)
22+ * - 후보가 사용된 횟수를 관리하기 => O(K)
23+ * > O(N) + O(K)
24+ * Time Complexity: O(N)
25+ * - 후보 하나를 선택해서 target과 비교 => O(N^M)
26+ * - target이 0이 되거나 누적 값이 더 커질 때까지 스택을 쌓기
27+ * - 최대 누적할 수 있는 횟수는 40 / 2 = 20회 => O(20) = O(M)
28+ * > O(N)*O(M)
29+ */
30+ public List <List <Integer >> combinationSum2 (int [] candidates , int target ) {
31+ Set <List <Integer >> set = new HashSet <>();
32+ Set <Integer > acc = new HashSet <>();
33+ int [] usedCount = new int [44 ];
34+ dfs (set , acc , usedCount , target , candidates );
35+
36+ List <List <Integer >> ans = new ArrayList <>(set );
37+ return ans ;
38+ }
39+
40+ /**
41+ * set: return용 조합 저장
42+ * acc: 사용 후보 누적
43+ * usedCount: 후보별 사용된 횟수 저장
44+ * target: 만들 수
45+ */
46+ private void dfs (Set <List <Integer >> set , Set <Integer > acc , int [] usedCount , int target , int [] candidates ) {
47+ // 완성된 경우 리턴하기
48+ if (target == 0 ) {
49+ // System.out.println("==========완성!! -> "+acc);
50+ List <Integer > tmp = new ArrayList <>();
51+ for (int n : candidates ) {
52+ if (acc .contains (n )) {
53+ for (int i = 0 ; i < usedCount [n ]; i ++) {
54+ tmp .add (n );
55+ }
56+ }
57+ }
58+ set .add (tmp );
59+ return ;
60+ }
61+
62+ for (int n : candidates ) {
63+ // target 보다 작은 후보 사용하기
64+
65+ if (target >= n ) {
66+ // System.out.println("candi->"+n);
67+ usedCount [n ]++;
68+ acc .add (n );
69+ // System.out.println(". next target->"+(target-n));
70+ dfs (set , acc , usedCount , target - n , candidates );
71+ // 원복하기
72+ usedCount [n ]--;
73+ if (usedCount [n ] == 0 ) {
74+ acc .remove (n );
75+ }
76+ }
77+ }
78+ }
79+ }
0 commit comments