|
| 1 | +/* |
| 2 | + * @lc app=leetcode.cn id=39 lang=golang |
| 3 | + * |
| 4 | + * [39] 组合总和 |
| 5 | + * |
| 6 | + * https://leetcode.cn/problems/combination-sum/description/ |
| 7 | + * |
| 8 | + * algorithms |
| 9 | + * Medium (72.34%) |
| 10 | + * Likes: 2684 |
| 11 | + * Dislikes: 0 |
| 12 | + * Total Accepted: 829.3K |
| 13 | + * Total Submissions: 1.1M |
| 14 | + * Testcase Example: '[2,3,6,7]\n7' |
| 15 | + * |
| 16 | + * 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target |
| 17 | + * 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。 |
| 18 | + * |
| 19 | + * candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 |
| 20 | + * |
| 21 | + * 对于给定的输入,保证和为 target 的不同组合数少于 150 个。 |
| 22 | + * |
| 23 | + * |
| 24 | + * |
| 25 | + * 示例 1: |
| 26 | + * |
| 27 | + * |
| 28 | + * 输入:candidates = [2,3,6,7], target = 7 |
| 29 | + * 输出:[[2,2,3],[7]] |
| 30 | + * 解释: |
| 31 | + * 2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。 |
| 32 | + * 7 也是一个候选, 7 = 7 。 |
| 33 | + * 仅有这两种组合。 |
| 34 | + * |
| 35 | + * 示例 2: |
| 36 | + * |
| 37 | + * |
| 38 | + * 输入: candidates = [2,3,5], target = 8 |
| 39 | + * 输出: [[2,2,2,2],[2,3,3],[3,5]] |
| 40 | + * |
| 41 | + * 示例 3: |
| 42 | + * |
| 43 | + * |
| 44 | + * 输入: candidates = [2], target = 1 |
| 45 | + * 输出: [] |
| 46 | + * |
| 47 | + * |
| 48 | + * |
| 49 | + * |
| 50 | + * 提示: |
| 51 | + * |
| 52 | + * |
| 53 | + * 1 <= candidates.length <= 30 |
| 54 | + * 2 <= candidates[i] <= 40 |
| 55 | + * candidates 的所有元素 互不相同 |
| 56 | + * 1 <= target <= 40 |
| 57 | + * |
| 58 | + * |
| 59 | + */ |
| 60 | +package jzoffer |
| 61 | + |
| 62 | +import ( |
| 63 | + "fmt" |
| 64 | + "sort" |
| 65 | +) |
| 66 | + |
| 67 | +// @lc code=start |
| 68 | +func combinationSumMy(candidates []int, target int) (res [][]int) { |
| 69 | + sort.Ints(candidates) |
| 70 | + visited := make(map[string]bool) |
| 71 | + var backtrace func(left int, path []int) |
| 72 | + backtrace = func(left int, path []int) { |
| 73 | + if left < 0 { |
| 74 | + return |
| 75 | + } |
| 76 | + if left == 0 { |
| 77 | + sort.Ints(path) |
| 78 | + if _, ok := visited[fmt.Sprintf("%v", path)]; ok { |
| 79 | + return |
| 80 | + } |
| 81 | + visited[fmt.Sprintf("%v", path)] = true |
| 82 | + // item := make([]int, len(path)) |
| 83 | + // copy(item, path) |
| 84 | + res = append(res, path) |
| 85 | + return |
| 86 | + } |
| 87 | + for _, v := range candidates { |
| 88 | + if left-v < 0 { |
| 89 | + break |
| 90 | + } |
| 91 | + path = append(path, v) |
| 92 | + // 必须copy,否则会影响backtrace的递归 |
| 93 | + p := make([]int, len(path)) |
| 94 | + copy(p, path) |
| 95 | + backtrace(left-v, p) |
| 96 | + path = path[:len(path)-1] |
| 97 | + } |
| 98 | + } |
| 99 | + backtrace(target, []int{}) |
| 100 | + return |
| 101 | +} |
| 102 | + |
| 103 | +// 作者:ukcuf |
| 104 | +// 链接:https://leetcode.cn/problems/combination-sum/ |
| 105 | +// 来源:力扣(LeetCode) |
| 106 | +// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 |
| 107 | +func combinationSum(candidates []int, target int) [][]int { |
| 108 | + sort.Ints(candidates) |
| 109 | + return dfs(candidates, target) |
| 110 | +} |
| 111 | + |
| 112 | +func dfs(candidates []int, target int) [][]int { |
| 113 | + ret := [][]int{} |
| 114 | + for i, d := range candidates { |
| 115 | + if target-d < 0 { |
| 116 | + break |
| 117 | + } else if target-d == 0 { |
| 118 | + ret = append(ret, []int{d}) |
| 119 | + continue |
| 120 | + } |
| 121 | + for _, v := range dfs(candidates[i:], target-d) { |
| 122 | + ret = append(ret, append([]int{d}, v...)) |
| 123 | + } |
| 124 | + } |
| 125 | + return ret |
| 126 | +} |
| 127 | + |
| 128 | +// @lc code=end |
0 commit comments