0040-组合总和II


给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

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

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

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:

[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出:

[
[1,2,2],
[5]
]
``` 

提示:

1 <= candidates.length <= 100
1 <= candidates[i] <= 50
1 <= target <= 30

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum-ii

参考:
- https://leetcode-cn.com/problems/combination-sum-ii/solution/dai-ma-sui-xiang-lu-dai-ni-xue-tou-hui-s-ig29/

## python

0040-组合总和II

class Solution:
def combinationSum2(self, candidates: [int], target: int) -> [[int]]:
res = []
path = []

    def backTrack(candidates, target, sum, startIndex):
        if sum == target:
            res.append(path[:])
        for i in range(startIndex, len(candidates)):
            if sum + candidates[i] > target:
                return
            # 去重
            if i > startIndex and candidates[i] == candidates[i-1]:
                continue
            sum += candidates[i]
            path.append(candidates[i])
            backTrack(candidates, target, sum, i+1) # 递归
            sum -= candidates[i] # 回溯
            path.pop()

    candidates = sorted(candidates)
    backTrack(candidates, target, 0, 0)
    return res
## golang

package backTrack

import "sort"

// 回溯-去重-层去重
func combinationSum2(candidates []int, target int) [][]int {
var path []int
var res [][]int
var history map[int]bool
history = make(map[int]bool)
sort.Ints(candidates)
backtrackSum2(0,0,target,candidates,path,&res,history)
return res
}

func backtrackSum2(startIndex,sum,target int, candidates, path []int, res *[][]int, history map[int]bool) {
// 终止条件
if sum == target {
tmp := make([]int, len(path))
copy(tmp, path)
res = append(res, tmp)
return
}
if sum > target {return}
// 回溯
// used[i - 1] == true,说明同一树支candidates[i - 1]使用过
// used[i - 1] == false,说明同一树层candidates[i - 1]使用过
for i:=startIndex;i // 去重
if i>0 && candidates[i] == candidates[i-1] && history[i-1] == false {
continue
}
// update path && sum
path = append(path, candidates[i])
sum += candidates[i]
history[i] = true
// 递归
backtrackSum2(i+1,sum,target,candidates,path,res,history)
// 回溯
path = path[:len(path)-1]
sum -= candidates[i]
history[i] = false
}
}