Skip to content
On this page

组合总和

Question

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

思路

39.组合总和

根据之前的组合总和III的代码,稍加修改就可以实现

js
var combinationSum = function(candidates, target) {
    const res = []  // 结果[][]
    const path = [] // 每次递归的结果[]
    let sum = target
    const backtracking = ()=>{
        if (sum < 0) { // 剪枝操作
            return; // 如果path.size() == k 但sum != n 直接返回
        }
        if( sum===0 ){		//终止条件
            res.push([...path])		
            return
        }
        for(let i=0; i< candidates.length ; i++){	// 本层集合中元素
            path.push(candidates[i])	
            sum-= candidates[i]			
            backtracking()		
            path.pop()
            sum+= candidates[i]			
        }
    }
    backtracking()
    return res
};

此时有一个问题:结果集中存在一些重复的结果

image-20230615100730357

如何解决呢?添加一个startIndex变量

js
var combinationSum = function(candidates, target) {
    const res = []  // 结果[][]
    const path = [] // 每次递归的结果[]
    let sum = target
    // startIndex :每次递归的起使位置
    const backtracking = (startIndex)=>{
        if (sum < 0) { // 剪枝操作
            return; // 如果path.size() == k 但sum != n 直接返回
        }
        if( sum===0 ){		//终止条件
            res.push([...path])		
            return
        }
        for(let i=startIndex; i< candidates.length ; i++){	// 本层集合中元素
            path.push(candidates[i])	
            sum-= candidates[i]			
            backtracking(i)		
            path.pop()
            sum+= candidates[i]			
        }
    }
    backtracking(0)
    return res
};

剪枝优化

39.组合总和1

如果下一层的sum(就是本层的 sum + candidates[i])已经大于target,就可以结束本轮for循环的遍历

js
var combinationSum = function(candidates, target) {
    const res = []  // 结果[][]
    const path = [] // 每次递归的结果[]
    let sum = target
    // startIndex :每次递归的起使位置
    const backtracking = (startIndex)=>{
        if (sum < 0) { // 剪枝操作
            return; // 如果path.size() == k 但sum != n 直接返回
        }
        if( sum===0 ){		//终止条件
            res.push([...path])		
            return
        }
        for(let i=startIndex; i< candidates.length; i++){	// 本层集合中元素
            if(sum-candidates[i] < 0 ) continue //剪枝优化
            path.push(candidates[i])	
            sum-= candidates[i]			
            backtracking(i)		
            path.pop()
            sum+= candidates[i]			
        }
    }
    backtracking(0)
    return res
};