您的位置:首页 > 其它

[LeetCode#40]Combination Sum II

2015-08-21 23:49 323 查看
Problem:

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]


Analysis:

A wrong solution:
-----------------
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> ret = new ArrayList<List<Integer>> ();
if (candidates == null || candidates.length == 0 || target == 0)
return ret;
ArrayList<Integer> item = new ArrayList<Integer> ();
Arrays.sort(candidates);
for (int i = 0; i < candidates.length; i++)
helper(candidates, i, ret, item, target, 0);
return ret;
}

public void helper(int[] candidates, int index, List<List<Integer>> ret, ArrayList<Integer> item, int target, int cur_total)     {
if (candidates[index] + cur_total >= target) {
return;
} else if (candidates[index] + cur_total == target) {
ArrayList<Integer> temp = new ArrayList<Integer> (item);
temp.add(candidates[index]);
ret.add(temp);
} else {
item.add(candidates[index]);
for (int i = index + 1; i < candidates.length; i++)
helper(candidates, index + 1, ret, item, target, cur_total + candidates[index]);
item.remove(item.size() - 1);
}
}

This solution does not take the constraint, that no duplicate combination is allowed in the result set, into consideration.
helper(candidates, index + 1, ret, item, target, cur_total + candidates[index]);

As the same design issue in N-Queens 2, we should not try to pass the specific search direction during the recurive, that would incure a lot of child call. We should try to test each possible placement at its step.
We should change
form a: helper(candidates, index + 1, ret, item, target, cur_total + candidates[index]);
meaning: The next placement is candidate[index+1].
--------------------------------------------------------------------------------
item.add(candidates[index]);
for (int i = index + 1; i < candidates.length; i++)
helper(candidates, index + 1, ret, item, target, cur_total + candidates[index]);
item.remove(item.size() - 1);

into

form b: helper(candidates, index + 1, target-candidates[i], item, ret);
meaning: We should start try to place(add) next placement from candidates[index + 1] to candidates[length()-1].
--------------------------------------------------------------------------------
for(int i=start;i<num.length;i++) {
if(i>start && num[i]==num[i-1]) continue;
item.add(num[i]);
helper(num,i+1,target-num[i],item,res);
tem.remove(item.size()-1);
}

Note in the form a, we have no idea weather the current placement is a duplicate or not!!!
Case : candidate: 1, 1, 1, 1, 2  target: 4
112
112 (1 result in duplicate)
1112 (no 1 is not a duplicate)
When you try to place 1 into the item, you have no idea it would result in duplicate or not.
Idea: If we could avoid the same element to be repetively placed at the same position of the reuslt string, we can avoid duplicate.
1, 1, 1, 2 (each 1 is placed at individual position)
1, 1, 1(1), 2 (for position 2, we have already placed 1 at this position, we should never try to place 1 at this position again, otherwise, the duplicate case would happen)

In the form b, we could easily detect this situation. Casue at current search, we try to place each candiate into a specific position(item.size()).

for (int i = start; i < candidates.length; i++) {
if (i > start && candidates[i] == candidates[i-1]) continue;
item.add(candidates[i]);
helper(i+1, candidates, target-candidates[i], item, ret);
item.remove(item.size()-1);
}

if(i>start && num[i]==num[i-1]) continue; Note the checkign i > start. try to differentiate the situation of 1, 1 with 1(1) This checking perfectly avoid the same value was placed at the same position again. It's so elegant and perfect.


Solution:

public class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> ret = new ArrayList<List<Integer>> ();
if (candidates == null || candidates.length == 0 || target <= 0)
return ret;
Arrays.sort(candidates);
ArrayList<Integer> item = new ArrayList<Integer> ();
helper(0, candidates, target, item, ret);
return ret;
}

public void helper(int start, int[] candidates, int target, ArrayList<Integer> item, List<List<Integer>> ret) {
if (target == 0) {
ret.add(new ArrayList<Integer> (item));
return;
}
if (target < 0 || start >= candidates.length)
return;
for (int i = start; i < candidates.length; i++) { if (i > start && candidates[i] == candidates[i-1]) continue; item.add(candidates[i]); helper(i+1, candidates, target-candidates[i], item, ret); item.remove(item.size()-1); }
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: