My code here will generate all combinations (repetition included) of the values in candidates such that the values will sum up to target. This is my solution to https://leetcode.com/problems/combination-sum/.
I am a little confused about why I need to include the following line of code:
currentSet = new ArrayList<>(currentSet);
This will essentially make it so that currentSet is a private variable for all recursive calls. Otherwise, currentSet will be a shared variable that the recursive calls will concurrently modify resulting in issues. For example when the statement above is omitted from the code,
combinationSum({1, 2}, 4) has the following output:
[[1, 1, 2], [1, 1, 1, 1], [1, 2]]
The array [1,2] obviously does not sum up to 4. Can anybody provide a solid explanation why this is happening?
Also, are there any optimizations I could do so that my code can avoid putting in duplicate but reordered arrays, as my current method in brute-force sorting and checking if contained in the HashSet leads to very bad complexity.
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Set<List<Integer>> returnSet = new HashSet<>();
returnSet = combSum(candidates, target, 0, returnSet, new ArrayList<Integer>());
return new ArrayList<>(returnSet);
}
private Set<List<Integer>> combSum(int[] candidates, int target, int i, Set<List<Integer>> returnSet,
List<Integer> currentSet) {
currentSet = new ArrayList<>(currentSet);
if(i == target) {
Collections.sort(currentSet);
if(!returnSet.contains(currentSet)) {
returnSet.add(new ArrayList<Integer>(currentSet));
}
} else if(i <= target){
System.out.println("Current set: " + returnSet.toString());
System.out.println("Current sum: " + i + " current target: " + target);
for(int a: candidates) {
if(i + a <= target) {
System.out.println("\tAdding: " + a + " so that the new sum will be: " + (i + a));
currentSet.add(a);
returnSet = combSum(candidates, target, i + a, returnSet, currentSet);
currentSet.remove(currentSet.size() - 1);
}
}
}
return returnSet;
}