leetcode 39. 组合总和 golang实现

描述
给定一个无重复元素的数组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]  //pre 为路径的上一个candidate
	}
	for _, candidate := range candidates {
		if cur+candidate <= target && candidate >= pre {
			tmpCurRet := make([]int, 0)// 注意2
			tmpCurRet = append(tmpCurRet, curRet...)
			tmpCurRet = append(tmpCurRet, candidate)

			ret = combinationSumBackTracking(cur+candidate, tmpCurRet, candidates, target, ret)

		}
	}

	return ret
}

你可能感兴趣的:(算法,数据结构,go)