LeetCode OJ-40-Combination Sum II

题目:

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
Each number in C 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.
For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]

大意:

从给定数组中找到一组数字,要求这组数字之和等于target。另外,数组中的数字不允许被使用多次,但如果一开始就存在多个的话,可以使用多次。

思路:

本题与39题略有不同,但大致思路还是一样的。先给candidates数组排个序,然后dfs进行递归回溯。
需要注意的是:
1、在同一层递归树中,如果某元素已经处理并进入下一层递归,那么在这一层与该元素相同的值就应该跳过。否则将出现重复。
例如:1,1,2,3
如果第一个1已经处理并进入下一层递归1,2,3
那么在本次递归中的第二个1就应该跳过,因为后续所有情况会被上一行的计算覆盖掉。

2、相同元素第一个进入下一层递归,而不是任意一个
例如:1,1,2,3
如果第一个1已经处理并进入下一层递归1,2,3,那么两个1是可以同时成为可行解的。
而如果选择的是第二个1并进入下一层递归2,3,那么不会出现两个1的解了。这里只需要对candidates数组排好序后按顺序访问即可。

代码:

public class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        List<Integer> current = new ArrayList<Integer>();
        Arrays.sort(candidates);
        combinationSum2(result, current, 0, candidates, target);
        return result;
    }

    private void combinationSum2(List<List<Integer>> result, List<Integer> current, int start, int[] candidates, int target) {
        //找到一组可行解,放入result中
        if(target == 0) {
            List<Integer> temp = new ArrayList<Integer>(current);
            result.add(temp);
            return;
        }

        //prev保证在同一层内,不会使用相同值得元素,从而避免求出重复值
        int prev = 0;
        for(int i = start; i < candidates.length; i++) {
            if(target < candidates[i]) {
                return;
            }
            //与上次访问的元素不相等
            if(prev != candidates[i]) {
                current.add(candidates[i]);
                combinationSum2(result, current, i + 1, candidates, target - candidates[i]);
                //退回上一层递归,把在之前递归层里放入的元素去掉
                current.remove(current.size() - 1);
                prev = candidates[i];
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值