Leetcode_40_CombinationSumII--数组元素组合,和为目标值,一个元素只可用一次,输出每种组合,每种组合唯一

Posted 二十六画生的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode_40_CombinationSumII--数组元素组合,和为目标值,一个元素只可用一次,输出每种组合,每种组合唯一相关的知识,希望对你有一定的参考价值。

Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sum to target.

Each number in candidates may only be used once in the combination.

Note: The solution set must not contain duplicate combinations.

Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8
Output: 
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

Example 2:

Input: candidates = [2,5,2,1,2], target = 5
Output: 
[
[1,2,2],
[5]
]

Constraints:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30
package com.backtrack;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Author you guess
 * @Date 2022/5/2 00:14
 * @Version 1.0
 * @Desc 回溯
 * 本题比较经典,回溯法!
 * 数组元素组合,和为目标值,一个元素只可用一次,输出每种组合,每种组合唯一
 */
public class Leetcode_40_CombinationSumII 


    /**
     * 正确方法:
     * Runtime: 5 ms, faster than 65.47% of Java online submissions for Combination Sum II.
     * Memory Usage: 42.7 MB, less than 80.23% of Java online submissions for Combination Sum II.
     * RIGHT Answer
     * Input
     * [10,1,2,7,6,1,5]
     * 8
     * Output
     * [[1,1,6],[1,2,5],[1,7],[1,2,5],[1,7],[2,6]]
     * Expected
     * [[1,1,6],[1,2,5],[1,7],[2,6]]
     *
     * @param candidates
     * @param target
     * @return
     */
    public List<List<Integer>> combinationSum2(int[] candidates, int target) 
        List<List<Integer>> result = new ArrayList();
        List<Integer> subResult = new ArrayList();
        Arrays.sort(candidates);
        //无需排序,直接下一步
        combinationSum(candidates, 0, target, subResult, result);
        return result;
    

    //方法重载
    private void combinationSum(int[] candidates, int startIndex, int target, List<Integer> subResult, List<List<Integer>> result) 
        if (target < 0) 
            return; // No combination is possible
        
        if (target == 0) 
            //需要使用新的集合对象,不然当subSet元素变化时allSet也会同时变化
            result.add(new ArrayList(subResult)); // If target is reached, add this combination to result
            return;
        
        /**
         * Use startIndex so that same candidate values are not picked again
         * Without startIndex, if we use 0, we will get permutations,
         * i.e. repeat of same combinations but in different orders. Try it
         */
        for (int i = startIndex; i < candidates.length; i++) 
//            if (i > 0 && candidates[i - 1] == candidates[i]) 
//                continue;
//            // 结果是[[1, 2, 5], [1, 7], [2, 6]],少了[1, 1, 6],是错误的。

            //i大于起始位置才与上一位比较是否重复
            if (startIndex < i && candidates[i - 1] == candidates[i]) 
                continue;
             // 结果是[[1, 1, 6], [1, 2, 5], [1, 7], [2, 6]]

            subResult.add(candidates[i]);
            int remainingTarget = target - candidates[i];
            combinationSum(candidates, i + 1, remainingTarget, subResult, result);
            //回溯,删除上次添加到末尾的元素
            subResult.remove(subResult.size() - 1); // Backtrack, remove the last element added
        
    


    public static void main(String[] args) 
        Leetcode_40_CombinationSumII main = new Leetcode_40_CombinationSumII();
//        System.out.println(main.combinationSum2(new int[]10, 1, 2, 7, 6, 1, 5, 8));//[[1, 1, 6], [1, 2, 5], [1, 7], [2, 6]]
//        System.out.println(main.combinationSum2(new int[]1, 1, 2, 2, 5, 5, 7));//[[1, 1, 5], [2, 5]]
        System.out.println(main.combinationSum2(new int[]1, 1, 1, 3));//[[1, 1, 1]]
    


    /**
     * Wrong Answer
     * Details
     * Input
     * [10,1,2,7,6,1,5]
     * 8
     * Output
     * [[1,1,6],[1,2,5],[1,7],[1,2,5],[1,7],[2,6]]
     * Expected
     * [[1,1,6],[1,2,5],[1,7],[2,6]]
     *
     * @param candidates
     * @param target
     * @return
     */
    public List<List<Integer>> combinationSum22(int[] candidates, int target) 
        List<List<Integer>> result = new ArrayList();
        List<Integer> subResult = new ArrayList();
        Arrays.sort(candidates);
        //无需排序,直接下一步
        combinationSum23(candidates, 0, target, subResult, result);
        return result;
    

    //方法重载
    private void combinationSum23(int[] candidates, int startIndex, int target, List<Integer> subResult, List<List<Integer>> result) 
        if (target < 0) 
            return; // No combination is possible
        
        if (target == 0) 
            //需要使用新的集合对象,不然当subSet元素变化时allSet也会同时变化
            result.add(new ArrayList(subResult)); // If target is reached, add this combination to result
            return;
        

        for (int i = startIndex; i < candidates.length; i++) 
            subResult.add(candidates[i]);
            int remainingTarget = target - candidates[i];
            combinationSum(candidates, i + 1, remainingTarget, subResult, result);
            //回溯,删除上次添加到末尾的元素
            subResult.remove(subResult.size() - 1); // Backtrack, remove the last element added
        
    


 

以上是关于Leetcode_40_CombinationSumII--数组元素组合,和为目标值,一个元素只可用一次,输出每种组合,每种组合唯一的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode_40_CombinationSumII--数组元素组合,和为目标值,一个元素只可用一次,输出每种组合,每种组合唯一

40.leetcode17_letter_combinations_of_a_phone_number

剑指offer_40_最小的 K 个数

LeetCode_136_SingleNumber

LeetCode_338_CountingBits

LeetCode_258_AddDigits