39. 组合总和

61 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

39. 组合总和

题目分析

题目给出一个无重复元素的整数数组和一个目标整数,要求找出数组中可以使数字和为目标数的所有不同组合,并以列表形式返回。

这道题与上次组合题目的区别在于,数组中同一个数字可以无限制重复被选取。并且,题目对数组的数值进行限制(毕竟出现0就不好了)

这道题同样使用回溯算法的方式解决。

解题

由于上次我们已经做过类似的题目,这次就不再分析回溯的总体方式。

直接进行回溯三部曲:

  1. 递归函数的参数

对于这道题,我设定了两个参数,一个是横向循环for循环时的起始位置,另一个是循环过程中累加的和。

  1. 回溯函数终止条件

由于这道题没有限制取出的个数,所以并不能判断叶子节点为终止。这道题终止条件是当和等于目标值的时候收集结果,当和大于目标值的时候结束。

  1. 单层搜索的过程

横向for循环从起始值开始搜索整个集合,纵向通过递归向下进行遍历,注意本题元素可重复选取。

代码如下;

var combinationSum = function(candidates, target) {
    const res = [],path = []
    candidates.sort((a,b) => a - b)
    backstrack(0,0)
    return res
    function backstrack(j,sum) {
        if(sum === target) {
            res.push(Array.from(path))
            return
        }
        for(let i = j;i < candidates.length;i++) {
            const n = candidates[i]
            if(n > target - sum) break
            path.push(n)
            sum += n
            backstrack(i,sum)
            path.pop()
            sum -= n
        }
    }
};

从上面的代码可以看出,与上一道组合题相比,不同的点在于终止条件的判断以及回溯时i并不加一。

上面的代码已经进行剪枝操作,当和大于目标值时不进行递归操作。