40. Combination Sum II
class Solution { public List<List<Integer>> combinationSum2(int[] candidates, int target) { Arrays.sort(candidates); List<List<Integer>> result = new ArrayList<>(); List<Integer> tmp = new ArrayList<>(); dfs(result, tmp, candidates, target, 0); return result; } private void dfs(List<List<Integer>> result, List<Integer> tmp, int[] candidates, int target, int start){ if(target == 0){ result.add(new ArrayList<>(tmp)); return; } // if(target < 0) return; same as if(candidates[i] > target) return; // add a new element to the list for(int i = start; i < candidates.length; i++){ // check this element is same as the element before if(i - 1 >= start && candidates[i] == candidates[i - 1]) continue; // if current element is bigger than target , stop if(candidates[i] > target) return; tmp.add(candidates[i]); dfs(result, tmp, candidates, target - candidates[i], i + 1);// every element can be used only once, so i + 1 tmp.remove(tmp.size() - 1); } } }
Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
Each number in candidates 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.
Example 1:
Input: candidates =[10,1,2,7,6,1,5], target =8, A solution set is: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
Example 2:
Input: candidates = [2,5,2,1,2], target = 5, A solution set is: [ [1,2,2], [5] ]
idea: do two things, sort the array, and when we are on the current level trying out different elements, skip the elements if they have the
same value as the one before, like in permutation 2 , if i rememeber right, we continue within the for loop when we tring out different elements
when nums[i] == nums[i-1].
for example. we have 1 1 1 2 2 2 5
then for the first pos, we can have the first 1 , we are left with 1 1 2 2 2 5 (a)
for the first pos, we can have the second 1 , we are left with 1 1 2 2 2 5 (b)
now we realize that the first leftover is the same as the second leftover, so they are gonna produce the same result
so we want to prevent this from happening. so we skip all the 1 after the first 1 for the first pos,
and when we meet 2, we add the first 2 to the tmp list for the first pos, and skip all the other 2 after the
first 2. because
if we take the first 2 for the pos 1 , we are left with 1 1 2 2 5 (c)
if we take the second 2 for the pos 1, we are left with 1 1 2 2 5 (d)
two things to notice here ,
one thing is that 1 1 2 2 5 (c)might have some results in common with (a)
so in order not to let that happen, we use start index, so everytime we choose a number for the current level, the candidates for the next level is after the number
choosen for the current level. for example , in this case, if want to have 2 2 5 leftover , instead of 1 1 2 2 5
so remember use start index to only add numbers after the current number
another thing to notice is that (c) and (d) have the same number combinations, which means they are gonna produce the same result as well.
how to solve this problem? as said earlier, we skip the other 2 after we met the first 2 . in code, this is if(nums[i] == nums[i-1]) continue; within the for loop
which i++.
continue means dont do the following steps, back to the for loop and see if the next number is valid. in this code, the follwing steps is placing the current number
int the tmp list, and do dfs on it .
for(int i = start; i < candidates.length; i++){ // check this element is same as the element before if(i - 1 >= start && candidates[i] == candidates[i - 1]) continue; // if current element is bigger than target , stop if(candidates[i] > target) return; tmp.add(candidates[i]); dfs(result, tmp, candidates, target - candidates[i], i + 1);// every element can be used only once, so i + 1 tmp.remove(tmp.size() - 1); } } } combination sum II
Each number in candidates may only be used once in the combination. so the starting index for the next pos is i + 1. =========================
combination sum I
The same repeated number may be chosen from candidates unlimited number of times. so the starting index for the next pos is i.
what combination sum i and ii have in common is that both of them use start index to prevent from
looking back to previous elements, which cause duplicate combinations . and combination ii is sorted , because
there are duplicate elements in the input, so the duplicate elements on the same pos can cause duplicate combinatins as well,
so need to sort the array first and skip the duplicates , so that we don't do dfs on two things that are the same, we only pcik the
first one , and do dfs on its all possible combinations
for example, we have 1123
we pick the first 1 for pos 1, and the pos 2 can be 1, 2, 3
we don't pick the duplicate 1 (the second 1 ) for pos 1, because we would have the same thing as above, becsause
pos 1 is 1, pos 2 can still be 1, 2 , 3
for(int i = index; i < candidates.length; i++){ tmp.add(candidates[i]); dfs(result, tmp, candidates, target - candidates[i], i); // tmp backtrack recovery tmp.remove(tmp.size() - 1); } }
posted on 2018-07-18 08:06 猪猪🐷 阅读(87) 评论(0) 收藏 举报
浙公网安备 33010602011771号