描述
给定一个无重复元素的数组candidates和一个目标数target,找出candidates中所有可以使数字和为target的组合。
candidates中的数字可以无限制重复被选取。
说明:
所有数字(包括target)都是正整数。
解集不能包含重复的组合。
示例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]
]
思路
回溯法
1. 每次遍历candidates得到的candidate 即为一个分支 取临时变量cur + candidate <= target 时 可继续向下遍历
2. 剪枝条件为cur == target
需要注意:
1.每次继续更深度递归时,candidate 要大于路径中上一个candidate 否则会有重复的结果 比如例1 结果 [[2,2,3], [2,3,2], [3,2,2], [7]]
2. 由于golang 切片底层实现的原因 要用一个临时变量tmpRet保存结果 多个子节点公用父节点的切片 会出现子节点修改其他子节点的问题
实现
func combinationSum(candidates []int, target int) [][]int {
ret := make([][]int, 0)
if target == 0 || len(candidates) == 0 {
return ret
}
curRet := make([]int, 0)
ret = combinationSumBackTracking(0, curRet, candidates, target, ret)
return ret
}
func combinationSumBackTracking(cur int, curRet []int, candidates []int, target int, ret [][]int) [][]int {
if cur == target {
ret = append(ret, curRet)
return ret
}
var pre int
if len(curRet) > 0 {
pre = curRet[len(curRet)-1]
}
for _, candidate := range candidates {
if cur+candidate <= target && candidate >= pre {
tmpCurRet := make([]int, 0)
tmpCurRet = append(tmpCurRet, curRet...)
tmpCurRet = append(tmpCurRet, candidate)
ret = combinationSumBackTracking(cur+candidate, tmpCurRet, candidates, target, ret)
}
}
return ret
}