题目:

给定一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集不能包含重复的子集。你可以按 任意顺序 返回解集。

输入:nums = [1,2,3]

输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

输入:nums = [0]

输出:[[],[0]]

分析:

剑指offer79:所有子集(回溯法)_leetcode


具体操作详见注释

如果输入的集合有n个元素,由于每个元素都有2个选项,因此总的时间复杂度是O(2^n)。

代码:

import java.util.LinkedList;
import java.util.List;

public class Subsets {
public static void main(String[] args) {
Subsets subsets = new Subsets();
int[] nums = {1,2,3};
List<List<Integer>> subsets1 = subsets.subsets(nums);
System.out.println(subsets1);
}
public List<List<Integer>> subsets(int[] nums){
List<List<Integer>> result = new LinkedList<>();
if (nums.length == 0){
return result;
}
// 第一个参数是数组nums,包含输入集合的所有数字,可以逐一从集合中取出一个数字并选择是否将该数字添加到子集中。
// 第二个参数是当前取出的数字在数组nums中的下标,也代表递归层数。
// 第三个参数是当前子集。
// 第四个参数result是所有已经生成的子集。
helper(nums,0,new LinkedList<Integer>(),result);
return result;
}

private void helper(int[] nums, int index, LinkedList<Integer> subset, List<List<Integer>> result) {
if (index == nums.length){
// result添加的是subset的一个拷贝,而不是subset本身
// 因为之后还需要修改subset以便得到其他的子集,同时避免已经添加到result中的子集被修改,在result中添加subset的拷贝可以避免不必要的修改
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);
// 在回溯到父节点,以便尝试父节点的其他选项,在回溯父节点之前,应该清除已经对子集状态进行的修改
subset.removeLast();
}
}
}

剑指offer79:所有子集(回溯法)_数组_02