LC Combination Sum Series
Problems
LC39: Combination Sum I
In this problem, we do not have the limitation on using the single element multiple times, therefore we can use the backtracking algorithm and start next recursion from the index we are at each step.
Note that we should not do the recursion on all the elements in candidate array because we don’t want to output the same solution in any order e.g. [2,3,3], [3,2,3], [3,3,2]
, therefore we should not move backward the index.
Note that the candidates array has only distinct elements, therefore we will not count same solution in different order multiple times because of the duplicates in the array.
Also note that the candidates array is not sorted so we can’t prune the solution after we find at any index the sum already exceeds the target but we should keep traverse the whole candidate array. And it reminds me of sorting the array at very first place.
1 | class Solution { |
If we sort the array beforehand, then we can prune the search tree which would imporve our runtime overhead. Note that the time complexity won’t change, but the algorithm is improved for sure.
1 | public void dfs(List<List<Integer>> ans, List<Integer> temp, |
LC40: Combination Sum II
From the previous problem, we found that pruning
can only happens when the candidates array is sorted.
LC216: Combination Sum III
Find all valid combinations of k numbers that sum up to n such that the following conditions are true:
- Only numbers 1 through 9 are used.
- Each number is used at most once.
Return a list of all possible valid combinations. The list must not contain the same combination twice.
Solution
We can use depth-first-search to search to the deepest element that is possible to sum up to the target and backtracking all the possible combinations. We loop from 1 to 9 and each time we add one single number to the sum and do the check. We recursively try every combinations
- Base case: if sum == target and the count of elements are equal to k, add the NEW temp list to the answer list
Takeaways
- When we add the temp list to the answer, we should be aware of the reference copy here.
1 | // add the reference to temp to the ans list |
- If we define the private answer list out side the main function, there might be safety problems. For example, if we have 2 thread sharing the same object, even if the ans list is private, there still be a thread safety problem.
1 | class Solution { |
1 | Solution solution = new Solution(); |
- For
LinkedList
,ArrayList
andArrayDeque
they are different:LinkedList
can do removeLast() directly, and add and delete from both head and tail are O(1)ArrayList
does not provide removeLast() method, but we can do remove(size() - 1) to similarly, add and delete at head is O(n)ArrayDeque
is dynamic double-ended queue, not as efficient as ArrayList in searching but provide all searching, inserting and deleting at O(1)