40. 组合总和 II

leecode原题

题目

给定一个候选人编号的集合 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

解题思路

思路

这道题目和39.组合总和如下区别:

  1. 本题candidates中的每个数字在每个组合中只能使用一次
  2. 本题数组candidates的元素是有重复的,而39.组合总和是无重复元素的数组candidates

最后本题和39.组合总和要求一样,解集不能包含重复的组合

本题的难点在于区别2中:集合(数组candidates)有重复元素,但还不能有重复的组合

强调一下,树层去重的话,需要对数组排序!

要去重的是“同一树层上的使用过”,如果判断同一树层上元素(相同的元素)是否使用过了呢。

如果candidates[i] == candidates[i - 1] 并且 used[i - 1] == false,就说明:前一个树枝,使用了candidates[i - 1],也就是说同一树层使用过candidates[i - 1]

此时for循环里就应该做continue的操作。

在图中将used的变化用橘黄色标注上,可以看出在candidates[i] == candidates[i - 1]相同的情况下:

  • used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
  • used[i - 1] == false,说明同一树层candidates[i - 1]使用过

实现

源码

var (
    res  = make([][]int, 0) // 存放最终结果
    path = make([]int, 0)   // 存放临时结果
    used = make([]bool, 0)  // 存放是否使用了的标志
)

func backtracking(candidates []int, target int, sum int, startIndex int) {
    if sum > target {
        return
    }
    // 满足条件, 追加到最终结果中
    if sum == target {
        temp := make([]int, len(path))
        copy(temp, path)
        res = append(res, temp)
    }
    for i := startIndex; i < len(candidates) && sum+candidates[i] <= target; i++ { // 剪枝
        // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
        // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
        // 要对同一树层使用过的元素进行跳过
        if i > 0 && candidates[i] == candidates[i-1] && used[i-1] == false {
            continue
        }
        sum += candidates[i]
        path = append(path, candidates[i])
        used[i] = true
        backtracking(candidates, target, sum, i+1)
        sum -= candidates[i]
        path = path[:len(path)-1]
        used[i] = false
    }
}

func combinationSum2(candidates []int, target int) [][]int {
    // !!!!!先要进行排序
    sort.Ints(candidates)
    res = make([][]int, 0)
    path = make([]int, 0)
    used = make([]bool, len(candidates))
    backtracking(candidates, target, 0, 0)
    return res
}
Copyright © ROSEMARY666 2022 all right reserved,powered by Gitbook该文章修订时间: 2022-09-28 15:55:21

results matching ""

    No results matching ""