【17】回溯算法

思路:

一层一层循环 每层循环中调用递归进去 判断符合要求就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
}

猜你喜欢

转载自blog.csdn.net/weixin_67225910/article/details/132586600