leetcode原题:
给你一个无重复元素的整数数组 candidates 和一个目标整数 target ,
找出 candidates 中可以使数字和为目标数 target 的所有不同组合 ,并以列表形式返回。
你可以按任意顺序返回这些组合。
candidates 中的同一个数字可以无限制重复被选取。
如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
示例 1:
输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。
示例 2:
输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]
示例 3:
输入: candidates = [2], target = 1
输出: []
理解题干:可以重复使用数组中的元素相加等于目标整数
这道题还是为了巩固我上一题的思路所以特地找的相似的题目,还是用到了相同的知识点,只是有效括号组合用到了二叉树来分析,组合总和需要用到多叉树;然后依然相同的思路是深度优先遍历和回溯;
以例一为 🌰 ,用多叉树去理解流程就比较清晰,以 target
为起点,我的目标是用 target
减去数组元素最后的结果等于0;所以记录下 target
减去的元素,存到数组里,当树枝末梢为0时就是我们想要的答案之一;而当树枝末梢小于0时,就要进行剪枝;
然后为了避免出现重复的答案不能每次都用 target
去减数组的每一个元素,而是记录下之前剪去的元素,从他的下一个元素开始,这样结果里就不会出现重复的答案;
通过上面的分析,画出了下图的结果;箭头是部分遍历和回溯的过程;
然后开始写代码;首先需要封装一个用来深度优先遍历的方法,这个方法需要5个参数
- @param {number[]} cur 用来记录当前的路径,也就是剪的数组里的元素,当树末梢为0时就是我们需要的结果之一
- @param {number} target 用来被减的数值,也就是多叉树里的节点,节点小于等于0时停止遍历
- @param {number} candidates 题干里的元素
- @param {number} begin 开始的位置
- @param {number[]} res 需要返回的最后的结果
var dfs = function(cur,target,candidates,begin,res){
if(target<0) return // 节点小于0 直接返回
if(target==0) {
res.push(cur.slice()) // 节点等于0 添加路径到result 并返回,这里push需要深拷贝一下否则在回溯的时候使用pop,其实都是操作原数组,会使我们最后得到的结果都是空数组,然后因为JSON.parse(JSON.stingify())拷贝实在是太慢了,所以用到了数组方法里的slice
return
}
for(let i=begin; i<candidates.length; i++){
cur.push(candidates[i]) // 记录路径
dfs(cur,target-candidates[i],candidates,i,res) // 遍历
cur.pop() // 回溯
}
}
封装好方法后来到调用的方法体:
var combinationSum = function(candidates, target) {
let cur = [] // 定义路径
let res = [] // 定义结果result
dfs(cur,target,candidates,0,res) // 调用
return res
};
完整代码:
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function(candidates, target) {
let cur = []
let res = []
dfs(cur,target,candidates,0,res)
return res
};
var dfs = function(cur,target,candidates,begin,res){
if(target<0) return
if(target==0) {
res.push(cur.slice())
return
}
for(let i=begin; i<candidates.length; i++){
cur.push(candidates[i])
dfs(cur,target-candidates[i],candidates,i,res)
cur.pop()
}
}