这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战
题目
给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。
candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。
对于给定的输入,保证和为 target 的唯一组合数少于 150 个。
示例1
输入: candidates = [2,3,6,7], target = 7
输出: [[7],[2,2,3]]
示例2
输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]
思路
题目最后寻找的是所有可能不重复的组合,对于这种类型的题目,一般 回溯 算法都是比较好的解决方案。
有如下思路:
-
先对题目所给数组
candidates按从小到大排序 -
定义结果数组
ans -
定义一个递归的函数
getCombination,接收当前组合 Arr、当前目标值 currentTarget、当前索引 idx三个参数-
如果
currentTarget == 0,将Arr放入结果数组ans中,进行剪枝 -
从索引
idx开始遍历-
如果
candidates[i] > currentTarget,可以进行剪枝,因为之前已经进行过排序,后面的值都会大于currentTarget -
为了排除重复数据,判断
candidates[i] == candidates[i - 1]时,跳过当前循环continue -
定义下次递归的参数
newArr = [...arr, candidates[i]], newTarget = currentTarget - candidates[i], newIdx = i; -
进行下次递归
-
-
-
用初始值,启动递归函数
getCombination([], target, 0) -
递归结束后,
ans即为所求
代码如下
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function(candidates, target) {
candidates = candidates.sort((a, b) => a - b);
let ans = [];
const getCombination = (arr, currentTarget, idx) => {
if(currentTarget == 0) {
ans.push(arr);
return;
}
for(let i = idx; i < candidates.length; i++) {
if(candidates[i] > currentTarget) {
return;
}
if(candidates[i] == candidates[i - 1]) continue;
let newTarget = currentTarget - candidates[i];
let newArray = [...arr, candidates[i]];
getCombination(newArray, newTarget, i);
}
}
getCombination([], target, 0);
return ans;
};
小结
解决问题的思路很重要,一次性想要得出所有的结果是很难做到的。但是可以通过回溯算法的思想,一步一步的列举某种答案的可能性,如果当前答案是可能的,那么继续尝试搜索答案的可能;否则就进行剪枝操作,排除不可能的答案。
LeetCode 👉 HOT 100 👉 组合总和 - 中等题 ✅
合集:LeetCode 👉 HOT 100,有空就会更新,大家多多支持,点个赞👍
如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄