LeetCode 40. Combination Sum II(dfs)

给定一个候选数字集合和目标数字,找到所有候选数字的唯一组合,使得组合的数字之和等于目标值。题目要求每个候选数字仅使用一次。本文通过深度优先搜索算法解决此问题,并详细解释思路及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目来源:https://leetcode.com/problems/combination-sum-ii/

问题描述

40. Combination Sum II

Medium

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

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

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

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

A solution set is:

[

  [1, 7],

  [1, 2, 5],

  [2, 6],

  [1, 1, 6]

]

Example 2:

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

A solution set is:

[

  [1,2,2],

  [5]

]

------------------------------------------------------------

题意

给定一组正整数candidatescandidates中的数可以重复)和一个正整数target,要求输出所有candidates中和为target的组合,其中candidates中的每个数限制只能使用一次。

------------------------------------------------------------

思路

解法与姊妹题LeetCode 39. Combination Sum(dfs)类似,也是深度优先搜索求解并用栈记录搜索路径,需要改动的地方有二:

1. 由于不能重复使用candidates中的元素,故Line 37的dfs(candidates, target – candidates, i)改为dfs(candidates, target – candidates, i - 1)

2. 由于输出的结果不能有重复,例如target = 3, candidates = [2, 1, 1], 则结果应当为[[2, 1]]不应当是[[2, 1], [2, 1]]. 因此需要在dfs遍历candidates中比小于等于当前index的循环中增加当前candidate是否与上一个candidate重复的判断,如果重复,则不继续深搜了。

------------------------------------------------------------

代码

class Solution {
    private List<List<Integer>> sols;    // answer list
    private Stack<Integer> ans; // an answer stored in a stack
    {
        ans = new Stack<Integer>();
        sols = new LinkedList<>();
    }
    
    /**
    index: largest index in use
    */
    public void dfs(int[] candidates, int target, int index)
    {
        if (target == 0)
        {
            sols.add(new LinkedList<Integer>(ans));
            return;
        }
        if (index == -1)
        {
            return;
        }
        int mem = -1;
        for (int i=index; i>=0; i--)
        {
            if (target < candidates[i])
            {
                continue;
            }
            else
            {
                if (candidates[i] == mem)
                {
                    continue;
                }
                ans.push(candidates[i]);
                dfs(candidates, target-candidates[i], i-1);
                ans.pop();
                mem = candidates[i];
            }
        }
    }
    
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        int n = candidates.length;
        if (n == 0)
        {
            return Collections.emptyList();
        }
        Arrays.sort(candidates);
        dfs(candidates, target, n - 1);
        return sols;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值