Table of contents
Given problem
Given a set of distinct integers, S, return all possible subsets.
Belows are some constraints of this problem:
- Elements in a subset must be in non-descending order.
- The solution set must not contain duplicate subsets.
- Also, the subsets should be sorted in ascending ( lexicographic ) order.
- The list is not necessarily sorted.
For example:
If S = [1,2,3], a solution is:
[
[],
[1],
[1, 2],
[1, 2, 3],
[1, 3],
[2],
[2, 3],
[3],
]
Using iterative version
public static List<List<Integer>> subsetIII(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
res.add(new ArrayList<>());
for (int value : nums) {
List<List<Integer>> subSets = new ArrayList<>(res);
for (List<Integer> tmp : res) {
subSets.add(new ArrayList<>(tmp));
}
for (List<Integer> tmp : subSets) {
res.add(tmp);
}
}
return res;
}
The complexity of this problem:
- Time complexity: O(n * 2^n)
- Space complexity: O(n * 2^n)
Using backtracking
-
Using index is greater or equal than the array’s length to terminate backtracking
public static void main(String[] args) { int[] nums = {1, 2, 3}; List<List<Integer>> res = subset(nums); res.stream().forEach(values -> { System.out.print("["); values.stream().forEach(value -> System.out.print(value + ", ")); System.out.print("]"); System.out.println(); }); } public static List<List<Integer>> subset(int[] nums) { List<List<Integer>> res = new ArrayList<>(); subset(nums, res, new ArrayList<>(), 0); return res; } private static void subset(int[] nums, List<List<Integer>> res, List<Integer> values, int index) { res.add(new LinkedList<>(values)); for (int i = index; i < nums.length; ++i) { values.add(nums[i]); subset(nums, res, values, i + 1); values.remove(values.size() - 1); } }
-
Using the size of subarrays to iterate all cases
public static List<List<Integer>> subset(int[] nums) { List<List<Integer>> res = new ArrayList<>(); for (int sizeSub = 0; sizeSub <= nums.length; ++sizeSub) { subsetII(nums, res, new ArrayList<>(), 0, sizeSub); } return res; } public static void subset(int[] nums, List<List<Integer>> res, List<Integer> values, int index, int k) { if (values.size() == k) { res.add(new ArrayList<>(values)); return; } for (int i = index; i < nums.length; ++i) { values.add(nums[i]); subsetII(nums, res, values, i + 1, k); values.remove(values.size() - 1); } }
The complexity of this problem:
- Time complexity: O(n * 2^n)
- Space complexity: O(n * 2^n)
Wrapping up
- The background of backtracking algorithm about listing all cases of a problem.
- There are an array - currentArr to contain the result of the current operations, and an array - finalArr to contain all final results.
- The specific condition to put currentArr to finalArr.
- If the current operation finished, the currentArr will get out of the current result to come back the previous results. Then, continue with the next operations.
Refer: