输入一个不含重复数字的数据集合,请找出它的所有子集。例如,数据集合[1,2]有4个子集,分别是[]、[1]、[2]和[1,2]。
如果集合中包含n个元素,那么生成子集可以分为n步,每一步从集合中取出一个数字,此时面临两个选择,将该数字添加到子集中或不将该数字添加到子集中。生成一个子集可以分为若干步,并且每一步都面临若干选择,这正是应用回溯法的典型场景。
public class Test {
public static void main(String[] args) {
int[] nums = {1, 2};
List<List<Integer>> result = subsets(nums);
for (List<Integer> item : result) {
System.out.println(item);
}
}
public static List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> result = new LinkedList<>();
if (nums.length == 0) {
return result;
}
helper(nums, 0, new LinkedList<Integer>(), result);
return result;
}
private static void helper(int[] nums, int index, LinkedList<Integer> subset, List<List<Integer>> result) {
if (index == nums.length) {
result.add(new LinkedList<>(subset));
}
else if (index < nums.length) {
helper(nums, index + 1, subset, result);// 直接不添加元素
subset.add(nums[index]);// 添加元素
helper(nums, index + 1, subset, result);
// 等递归函数执行完成之后,函数helper也执行完成,接下来将回到前一个数字的函数调用处继续执行。那么此时将回溯到父节点,以便尝试父节点的其他选项。
// 在回溯到父节点之前,应该清除已经对子集状态进行的修改。此前在子集subset中添加了一个数字,此时应该将它删除。
subset.removeLast();
}
}
}