Subsets
One of the two basic templates of depth first search.
Definition
- Ordered sets of parent set
- Elements in subsets should be continuous
Example
If S = [1,2,3], its subsets is:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]
Logical Steps
- Create a recursive helper function, start at a particular position in input as starting point.
- Recursively add element after position pointer into list (in a loop), and add lists into results.
- Backtrack to remove last element in previous list
- Move position cursor forward in next loop iteration for adding new elements into list.
Core Code Template
// Definition: nums, rst, list, pos
public void helper(nums, rst, list, pos) {
    // base condition:
    rst.add(new ArrayList<Integer>(list));
    // loop through all elements after pos to construct a list
    for (int i=pos; i<num.length; i++) {
        // add curr element into list
        list.add(num.get(i));
        // recur call helper, with pos = i+1
        helper(nums, rst, list, i+1);
        // backtrack, remove last element from list
        // and add in a different element next time
        list.remove(list.size()-1);
    }
}
Common Mistakes
- When adding list into results, directly add list object into result will create empty entries in result. Need to create a new Array List object for list.
- In helper function, will need a loop to go through all elements after start position, and call helper(nums, rst, list, i+1). If goes with no loop and helper(nums, rst, list, pos+1) directly, no new element can fill in to create new lists.
Follow Up: decuplication
There are duplicate numbers coming from input set, return all subsets. Each subset cannot have duplicate elements, but can contain different elements with the same value If S = [1,2,2], the subsets are:
[
  [2],
  [1],
  [1,2,2],
  [2,2],  // the two 2's here are different elemt with same value
  [1,2],
  []
]
Logical Steps: deduplication
- After backtrack, we need to make sure the element added into list (nums[i]) is not the previous element.
- Sort input numbers to put all duplicate numbers together
- Take only the first occurrence of duplicate numbers, since number position only appears in pos once, and only being taken when i=pos, all duplicate after i=pos are skipped.
Code Implementation: deduplicate
for (int i = pos; i<nums.length; i++) {
    /**
    * take first occurrence of duplicate numbers only
    * (when first occurrence was at pos)
    */
    if (i != pos && nums.get(i) == nums.get(i-1))
        continue;
    list.add(nums.get(i));
    helper(nums, rst, list, i+1);
    //backtrack
    list.remove(list.size()-1);
}