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.
  • Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ 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] 

Subscribe to see which companies asked this question

【题目分析】

相比较上一个题:39. Combination Sum,这个题目在一些细节上发生了变化,即最后生成的组合中某个数字出现的最大重复次数是给的候选数组中该数字的重复次数。

【思路】

我们在上个题的基础上进行改动,上个算法是采用了递归的方式。首先把数组排序,然后遍历数组中的每一个数字n,如果该数字小于当前的目标值,就在当前数字开始向后的那部分数中生成目标值等于target-n的组合,再把当前值加入到所有组合中,这个过程会保证每个数字可以重复任意需要的次数。如果每次递归时,改变递归开始的数字的下标,使其不包含当前数字,那么该数字就不会在最后的生成的组合中重复多次。但是这样存在一个问题就是,生成的某些组合会出现多次。

例如这样一个序列:[10,1,2,7,6,1,5] 排序后为:[1,1,2,5,6,7,10]. 如果只改变每次递归时候选数字开始的数组下标值,结果是这样的:

[1,1,6] [1,2,5] [1,7] [1,2,5] [1,7] [2,6]

我们发现[1,2,5] [1,7]重复出现了,这是为什么呢?因为在候选数组中1出现了两次,那么在见到第一个1时我们已经生成了关于1的所有组合,当遍历到第二个1时,自然会导致部分组合出现重复。解决的办法就是我们记录上一个遍历值的大小,如果当前值和上一个值相同,那么我们就跳过当前值。这样就不会出现生成的组合重复出现的现象。

【java代码】

 1 public class Solution {
 2     public List<List<Integer>> combinationSum2(int[] candidates, int target) {
 3         Arrays.sort(candidates);
 4         return combination(candidates, target, 0);
 5     }
 6     
 7     public List<List<Integer>> combination(int[] candidates, int target, int start) {
 8         List<List<Integer>> list = new ArrayList<>();
 9         if(candidates == null || candidates.length == 0) return list;
10         int last = 0;
11         
12         for(int i = start; i < candidates.length; i++){
13             if(candidates[i] == last) continue;
14             if(candidates[i] < target){
15                 List<List<Integer>> tlist = combination(candidates, target - candidates[i], i+1);
16                 if(tlist.size() > 0){
17                     for(List<Integer> alist : tlist){
18                         alist.add(0, candidates[i]);
19                     }
20                     list.addAll(tlist);
21                 }
22             }
23             else if(candidates[i] == target){
24                 List<Integer> tlist = new LinkedList<>();
25                 tlist.add(target);
26                 list.add(tlist);
27             }
28             else break;
29             last = candidates[i];
30         }
31         return list;
32     }
33 }
原文地址:https://www.cnblogs.com/liujinhong/p/5525390.html