LeetCode之求组合数之和二CombinationSumII

来源:互联网 发布:矩阵的伴随矩阵怎么求 编辑:程序博客网 时间:2024/06/08 07:11

问题描述:

/** * 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. *  * Elements in a combination (a1, a2, b & , ak) must be in non-descending order. (ie, a1 b  $ a2 b$ b & b $ ak). * 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。而且,不能有重复的组合。这个问题和前面问题不同的地方就是,每个数字只能用一次。前面那篇博文要求每个数字可以用很多次。所以只需要把前面的程序稍微修改一下即可。前面那篇的代码是这样的:

private static void combinationSum(int[] candidates, int start, int sum,            int target, ArrayList<ArrayList<Integer>> ret,            ArrayList<Integer> solution) {        if (sum == target) {            ret.add(new ArrayList<Integer>(solution));            return;        }        if (sum > target)            return;        for (int i = start; i < candidates.length; i++) {            solution.add(candidates[i]);            combinationSum(candidates, i, sum + candidates[i], target, ret, solution);            solution.remove(solution.size() - 1);        }    }

在for循环中,每次递归时,都是从i开始,也就是说,每次进行新一轮递归时,都是从这个数本身开始的,要想不重复使用这个数,那么每次递归时从i+1开始即可。(如果看到这有点绕的话,建议看一下前面那篇博文)。代码如下:

public static ArrayList<ArrayList<Integer>> combinationSum(int[] candidates,            int target) {        ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();        ArrayList<Integer> solution = new ArrayList<Integer>();        Arrays.sort(candidates);        combinationSum(candidates, 0, 0, target, ret, solution);        return ret;    }    private static void combinationSum(int[] candidates, int start, int sum,            int target, ArrayList<ArrayList<Integer>> ret,            ArrayList<Integer> solution) {        if (sum == target) {            ret.add(new ArrayList<Integer>(solution));            return;        }        if (sum > target)            return;        int pre = -1;           for (int i = start; i < candidates.length; i++) {            if (pre == candidates[i])                continue;            pre = candidates[i];            solution.add(candidates[i]);            combinationSum(candidates, i+1, sum + candidates[i], target, ret, solution);            solution.remove(solution.size() - 1);        }    }    //测试代码        public static void main(String args[])        {            int[]candidates = new int[]{10,1,2,7,6,1,5};            ArrayList<ArrayList<Integer>> result =combinationSum(candidates,8);            for(int i=0;i<result.size();i++)            {                System.out.print(result.get(i));            }        }

但是如果单单把i改为i+1,让每次递归时从后面一个数开始的话,并不能满足不允许有重复的组合,因为这样改的话如果有重复的数字就会出现重复的组合。所以在每次递归前加入了这样几行代码:

if (pre == candidates[i])    continue;pre = candidates[i];

一开始先把candidates[i]赋值给pre。然后在,若相同,则跳出,进行新一轮的递归。这样就可以跳过那些重复的数字。

0 0
原创粉丝点击