给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
思路
- 动态规划,维护 0 ~ target 的计算结果,最终输出 dp[target]
- dp[n] = candidate X dp[n - candidate] 结果的并集,其中 candidate 为 dp[n - candidate] 中最大的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var combinationSum = function (candidates, target) { candidates = candidates.sort((a, b) => a - b) const dp = [[[]]] for (let i = 1; i <= target; ++i) { dp[i] = [] for (const val of candidates) { if (val > i) { break } const itemsGroups = dp[i - val].filter((items) => items.length === 0 || items[items.length - 1] <= val) for (const items of itemsGroups) { dp[i].push([...items, val]) } } } return dp[target] }
|
其他思路
- 上述动态规划有个缺点,不能从容应对同一数字选取次数受限的情况
- 可以使用递归,传递游标位置解决这一问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var combinationSum = function (candidates, target) { candidates = candidates.sort((a, b) => a - b) const result = [] const searchTree = (startIndex, curVals, remainVal) => { if (remainVal === 0) { result.push(curVals) return } if (startIndex >= candidates.length || remainVal < 0) { return } searchTree(startIndex, [...curVals, candidates[startIndex]], remainVal - candidates[startIndex]) searchTree(startIndex + 1, curVals, remainVal) } searchTree(0, [], target) return result }
|