小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
题目
给定一个无重复元素的正整数数组 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]]
示例 3:
输入: candidates = [2], target = 1
输出: []
示例 4:
输入: candidates = [1], target = 1
输出: [[1]]
示例 5:
输入: candidates = [1], target = 2
输出: [[1,1]]
提示:
1 <= candidates.length <= 301 <= candidates[i] <= 200candidate中的每个元素都是独一无二的。1 <= target <= 500
解题思路
首先,明确题目环境:
- 数字可重复选取
- candidates和target都是正整数
考虑到【求和以及解不重复】,有过3数之和的经验:
- 想到必须先对candidates进行排序
- 利用判断当前数字与track的末尾数字比较,达到去重的目的
编写特殊情况
- candidates.length<=0
- target<candidates[0]
编写回溯函数backTrack,见代码
代码
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
// 数字可重复,全为正整数
var combinationSum = function(candidates, target) {
let res=[]
let len=candidates.length
if(len<=0)return res
candidates.sort((a,b)=>a-b)//从小到大排序
if(candidates[0]>target)return res //特殊,arr[0]>target
backTrack([],target)
return res
function backTrack(track,target){
if(target===0){//终止条件
res.push(track.slice())
return
}
for(let num of candidates){
if(num>target){//target决定取值范围
break
}
//注意去重,【2,2,3】【2,3,2】不难发现,这一位>=上一位
if(track.length!==0){
if(num>=track[track.length-1]){//判断该选择是否导致路径重复
track.push(num)
backTrack(track,target-num)
track.pop()
}else{//continue
continue
}
}else{//track无元素
track.push(num)
backTrack(track,target-num)
track.pop()
}
}
}
};
最后
曾梦想仗剑走天涯
看一看世界的繁华
年少的心总有些轻狂
终究不过是个普通人
无怨无悔我走我路