|
| 1 | +/** |
| 2 | + * @param {number[]} candidates |
| 3 | + * @param {number} target |
| 4 | + * @return {number[][]} |
| 5 | + */ |
| 6 | + |
| 7 | +/** |
| 8 | + * candidates를 여러번 사용해도 된다. 하지만 사용한 종류와 개수가 모두 같으면 안된다. |
| 9 | + * |
| 10 | + */ |
| 11 | +var combinationSum = function(candidates, target) { |
| 12 | + const candidatesLength = candidates.length |
| 13 | + // 시작 시점에서 array를 만들어서 넘겨줘야한다. |
| 14 | + // candidates 중에 넣으면 target이 되면 답에 그 배열을 넣고 탈출한다. |
| 15 | + // 만약 더했는데 target보다 크면 그냥 리턴한다. |
| 16 | + // target보다 작은것에 대해서 넣는다. |
| 17 | + const ret = [] |
| 18 | + function dp(total,newNum,currentArr){ |
| 19 | + if(total + newNum > target){ |
| 20 | + return |
| 21 | + } |
| 22 | + if(total + newNum == target && ){ |
| 23 | + ret.push([...currentArr,newNum]); |
| 24 | + return |
| 25 | + } |
| 26 | + |
| 27 | + //두 가지 어느것에도 해당하지 않으면 재귀를 또 다시 돈다. |
| 28 | + for(let i = 0; i<candidatesLength; i++){ |
| 29 | + dp(total+newNum , candidates[i],[...currentArr,candidates[i]]) |
| 30 | + } |
| 31 | + } |
| 32 | + dp(0,0,[]) |
| 33 | + return ret |
| 34 | +}; |
| 35 | + |
| 36 | +//여기서 문제가 생겼다. |
| 37 | +// 중복이 생긴다는 것이다. 어떻게 중복을 제거하면 좋을까? |
| 38 | +/** |
| 39 | + * 1. Set을 이용한다. |
| 40 | + * 2. 순서를 둔다. idx를 dfs에 넘겨주어서, 순서대로 작동하게 한다. |
| 41 | + */ |
| 42 | + |
| 43 | +var combinationSum = function(candidates, target) { |
| 44 | + const candidatesLength = candidates.length |
| 45 | + const ret = [] |
| 46 | + function dp(idx,total,currentArr){ |
| 47 | + if(total > target){ |
| 48 | + return |
| 49 | + } |
| 50 | + if(total == target){ |
| 51 | + ret.push(currentArr); |
| 52 | + return |
| 53 | + } |
| 54 | + |
| 55 | + //idx를 넘겨받아서, 그 이후의 것에만(자기 자신 포함) 돌게 된다. 그러면 절반정도만 돈다고 볼 수 있다. |
| 56 | + for(let i = idx; i < candidatesLength; i++){ |
| 57 | + dp(i,total+ candidates[i],[...currentArr,candidates[i]]) |
| 58 | + } |
| 59 | + } |
| 60 | + dp(0,0,[]) |
| 61 | + return ret |
| 62 | +}; |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | +/** |
| 67 | + 시간복잡도: O(N^(target/min)) : N개 후보 중 선택하는 경우의 수가 target/min 깊이만큼 반복 |
| 68 | +공간복잡도: O(target/min) : 재귀 스택의 최대 깊이가 target/min |
| 69 | +
|
| 70 | +
|
| 71 | + */ |
| 72 | + |
| 73 | + |
| 74 | +// 2. dp를 활용한 문제 해결방법 |
| 75 | +var combinationSum = function(candidates, target) { |
| 76 | + const dp = Array.from({length:target+1},()=>[]) |
| 77 | + dp[0] = [[]]; |
| 78 | + for(let candidate of candidates){ |
| 79 | + //여기서 candidate에 대해서, 이후 타겟까지 더할 수있는 숫자에 대한 조합에, candidate를 각각 넣어준다. |
| 80 | + for(let i = candidate; i <= target; i++){ |
| 81 | + for(let comb of dp[i-candidate]){ //각 조합에 넣어줌 |
| 82 | + dp[i].push([...comb,candidate]) |
| 83 | + } |
| 84 | + } |
| 85 | + } |
| 86 | + return dp[target] |
| 87 | +}; |
| 88 | +/** |
| 89 | +시간복잡도: O(N × target × M) |
| 90 | +N개 후보를 순회하면서, 각 후보마다 target까지의 값들에 대해 기존 조합들을 복사해서 새 조합을 생성하는데, 기존의 조합의 수 M을 곱해야함 |
| 91 | +공간복잡도: O(target × M) |
| 92 | +dp 배열의 각 인덱스에 해당 값을 만드는 모든 조합들을 저장. 조합개수에 따라서 커짐 |
| 93 | + */ |
0 commit comments