LeetCode Online Judge 题目C# 练习 - 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]

 1         public static List<List<int>> CominationSumII(int[] candidates, int target)
 2         {
 3             List<List<int>> ret = new List<List<int>>();
 4             List<int> O = new List<int>();
 5             Array.Sort(candidates);
 6             CombinationSumII(candidates, 0, O, target, ret);
 7 
 8             return ret;
 9         }
10 
11         public static void CombinationSumII(int[] I, int start, List<int> O, int sum, List<List<int>> ret)
12         {
13             if(sum == 0)
14             {
15                 List<int> temp = new List<int>(O);
16                 ret.Add(temp);
17                 return;
18             }
19 
20             if(start == I.Length || sum < 0)
21                 return;
22 
23             int prev = -1;
24             for(int i = start; i < I.Length; i++)
25             {
26                 if (I[i] != prev)
27                 {
28                     O.Add(I[i]);
29                     CombinationSumII(I, i + 1, O, sum - I[i], ret);
30                     O.RemoveAt(O.Count - 1);
31                     prev = I[i];
32                 }
33             }
34         }

代码分析:

  这一题跟combination Sum有点不一样了,candidates 中有重复的元素,但是又不能重复使用。想了很久怎么DP,答案是,很难。

  最后还是用递归比较方便。

  用题目的例子解释一下递归的过程:

  candidate set 10,1,2,7,6,1,5 and target 8, 

  先排列candidate set => 1,1,2,5,6,7,10

  {1} => {1,2,5,6,7,10} , target: 8-1=7

      {1,1} => {2,5,6,7,10}, target: 7-1=6

            {1,1,2} => {5,6,7,10}, target: 6-2=4;

                   {1,1,2,5} 5 > 4 回溯

            {1,1,5} => {6,7,10}, target: 6-5=1;

                  {1,1,5,6} 6 > 1 回溯

            {1,1,6} => {7,10}, target: 6-6=0; {1,1,6} 添加到return list。

            {1,1,7} 7 > 6 回溯

      {1,2} => {5,6,7,10},target: 7-2=5

           {1,2,5} => {6,7,10}, target: 5-5=0; {1,2,5} 添加到return list。

  ......

  要留意一点,因为题目要求不能有重复,所以用了 一个prev来存放递归前的一个数值,如果下一个值跟prev相同,则跳过。比如说,当我们递归回溯到第一步{1}, 然后循环到下一个{1}开始递归,这是prev = 1,所以我们就跳过第二个{1},直接到{2}继续递归。

  不明白的话可以试试注释掉有关prev变量的几行,跑跑题目的例子,会发现{1,7}, {1,2,5}会重复出现。

      20行已修改,感谢ffengfrank指出错误。

posted @ 2012-07-03 23:41  ETCOW  阅读(633)  评论(7编辑  收藏  举报