Idea:
Loop one level at a time, call recursion in each level loop, judge if it meets the requirements, and then return the traceback.
A bit abstract like finding your keys at home:
Start from the first floor of the house (for first floor loop (i=0))----->enter room a------>open the first box [not found] recursion
No more boxes---[Not found] Open the second box <-----Close the first box Backtracking
Exit room a------>enter room b----->open the first box...
Here entering the room and opening the box is like a recursive call, closing the box and closing the door is like backtracking.
Then here the accumulated sum == the goal is to find the key, otherwise we will continue to search one by one.
Code:
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
}