代码随想录回溯算法——组合总和II

题目

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

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

说明: 所有数字(包括目标数)都是正整数。 解集不能包含重复的组合。

示例 1: 输入: candidates = [10,1,2,7,6,1,5], target = 8, 所求解集为: [ [1, 7],
[1, 2, 5], [2, 6], [1, 1, 6] ]

示例 2: 输入: candidates = [2,5,2,1,2], target = 5, 所求解集为: [ [1,2,2],
[5] ]

思路

这题和组合总和有如下区别:

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

本题关键在于:集合中有重复数字,但是结果中不能有重复的组合(注意,只是两个组合不能相同,同一个组合内有重复的元素没关系)

我们去重去的是同一树层使用过的元素,同一树枝上的都是一个组合里的元素,不用去重,比如[1,1,2],在同一树枝上先选了1,可以接着选1,不用去重,但是在同一树层上,选了1已经选过了1,就不能重复选取了

强调:树层去重的话,需要对数组排序!(保证相同元素相邻)

回溯三部曲

  1. 回溯函数参数和返回值:增加一个bool型数组,用来记录同一树枝上的元素是否使用过
  2. 递归终止条件:sum == target或者sum > target
  3. 单层搜索的逻辑:对于去重操作,在candidates[i] == candidates[i - 1]的情况下(这里used数组只是方便理解,写代码的时候不一定要使用这个标记数组)
  • used[i - 1] == true,说明同一树枝candidates[i - 1]使用过 如[1,1,0],说明是同一树枝的重复元素,可以有重复
  • used[i - 1] == false,说明同一树层candidates[i - 1]使用过 比如[0,1,0],说明同一树层有重复元素,需要跳过

所以我们直接跳过同一树层的重复元素即可,先对数组排序,相同的就跳过:

if(i > start && candidates[i] == candidates[i-1]){
	continue;
}

java代码如下:

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        
        Arrays.sort(candidates);
        dfs(candidates,target,0);
        return res;
    
    }

    private void dfs(int[] candidates, int target,int index){
        
        if(target == 0){
            res.add(new ArrayList<>(path));
            return;
        }

        for(int i = index; i < candidates.length; i++){
            if(candidates[i] <= target){
                if(i > index && candidates[i] == candidates[i-1]){
                    continue;
                }
                path.add(candidates[i]);
                dfs(candidates,target-candidates[i],i+1);
                path.remove(path.size()-1);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HDU-五七小卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值