leetcode40. 组合总和 II (java-回溯算法)

组合总和 II

  • leetcode40. 组合总和 II
    • 题目描述
    • 解题思路
    • 代码演示
  • 回溯算法专题

leetcode40. 组合总和 II

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/combination-sum-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

解题思路

这题还是和子集问题是相同的求解套路,我们只要子集的一部分,
关于子集的解法,查看leetcode78 子集
我们是要子集中的一部分符合,和为target 的子集,因此我们只要加入判断就行了。
但是这里有个问题,就是重复值的问题,如果值有重复的,我们要进行减枝。
leetcode40. 组合总和 II (java-回溯算法)_第1张图片
重复的2 我们就不进行重复选择了,进行剪枝,代码里就是,我们先对数组排序,让相等的两个数相邻,然后递归时,判断已经选择过,就跳过。

代码演示

class Solution {
    List<List<Integer>> ans = new LinkedList<>();
    LinkedList<Integer> track = new LinkedList<>();
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    	//先对数组排序,方便剪枝
        Arrays.sort(candidates);
        process(candidates,0,target);
        return ans;
    }
	/**
	* 回溯算法,
	*/
    public void process(int[]candidates,int index,int target){
        //base case 小于0 前面选择无效,直接返回
        if(target < 0){
            return ;
        }
        //base case target == 0 ,选择是有效的,加入到目标集合里
        if(target == 0){
            ans.add(new LinkedList<>(track));
        }
        //越界时,直接返回。
        if(index == candidates.length){
            return;
        }
        //可以选择的列表
        for(int i = index;i < candidates.length;i++){
        	//剪枝操作,已经选择过的数字,不在进行重复选择
            if(i > index && candidates[i] == candidates[i - 1]){
                continue;
            }
            track.addLast(candidates[i]);
            //选择以后,目标数字减去选择的
            process(candidates,i + 1,target - candidates[i]);
            track.removeLast();
        }
    }
}

回溯算法专题

leetcode78 子集

leetcode77. 组合

你可能感兴趣的:(java,数据结构,算法,算法,java,leetcode,动态规划,数据结构)