思路:
一层一层循环 每层循环中调用递归进去 判断符合要求就return回溯
有点抽象 就像在家里找钥匙 :
先从家第一层(for第一层循环(i=0) )----->进入a房间------>打开第一个盒子【没找到】 递归
没有盒子了---【没找到】打开第二个盒子<-----关上第一个盒子 回溯
退出a房间------>进入b房间----->打开第一个盒子...
这里进入房间打开盒子就像是递归调用,关闭盒子 关上门就是回溯
那这里 现在累计的和==目标 就是找到钥匙了 否则就是继续一个一个找
代码:
func combinationSum(candidates []int, target int) [][]int {
//定义外部变量
var result [][]int
var currentCombination []int
sort.Ints(candidates) // 首先对数组进行排序
var backtrack func(startIdx, currentSum int)
backtrack = func(startIdx, currentSum int) {
//1)出口
if currentSum == target {
// 如果当前和等于目标值,将当前组合添加到结果中
result = append(result, append([]int{}, currentCombination...))
return
}
//2)开始遍历
for i := startIdx; i < len(candidates); i++ {
//1、和大于目标值
if currentSum+candidates[i] > target {
break // 如果当前和加上当前元素已经超过目标值,跳出循环
}
//2、排除重复项
if i > startIdx && candidates[i] == candidates[i-1] {
continue // 跳过重复的元素,避免重复的组合
}
// 若 和 小于 目标值
//放入这个元素
currentCombination = append(currentCombination, candidates[i]) // 将当前元素加入当前组合
//进入递归
backtrack(i, currentSum+candidates[i]) // 递归调用,继续查找下一个元素
//回溯出来的操作:取出这个元素
currentCombination = currentCombination[:len(currentCombination)-1] // 回溯,移除当前元素
}
}
backtrack(0, 0) // 从第一个元素开始查找
return result
}