40.组合总和 II

95 阅读1分钟

题目:
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意: 解集不能包含重复的组合。
算法:

func combinationSum2(candidates []int, target int) [][]int {
	ans := make([][]int, 0)
	result := make([]int, 0)
	cadidatasMap := make(map[int]int)
	for i := range candidates {
		cadidatasMap[candidates[i]] ++
	}
	cadidatasList := make([][]int, 0)
	for num, cnt := range cadidatasMap {
		cadidatasList = append(cadidatasList, []int{num, cnt, cnt})
	}

	var backtrack func(index, target int)
	backtrack = func(index, target int){
		if index >= len(cadidatasList) {
			return
		}
		
		if target == 0 {
			ans = append(ans, append([]int{}, result...))
			return
		}
		
		// cadidatas[index]相同的数字选择0个,
		// 为避免liine:39 backtrack重复进行选择0个cadidatas[index]的判断,去重
			backtrack(index + 1, target)

		// cadidatas[index]相同的数字选择[1,cadidatasList[index][1]]个
		if target - cadidatasList[index][0] >= 0 && cadidatasList[index][1] > 0 {
			result = append(result, cadidatasList[index][0])
			cadidatasList[index][1] --
			backtrack(index, target - cadidatasList[index][0])
			result = result[:len(result) - 1]
			cadidatasList[index][1] ++
		}
	}

	backtrack(0, target)
	return ans
}