(一)题目描述
给你一个整数数组 nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
(二)解题思路
1)看到所有子集都要列出来,就想到用排列+组合问题,所以自然而然就想到利用回溯来解决,先横向选第一个开始,深度纵向搜一次,每进行一次递归搜索,都需要把当前path加入二维数组res中(这是与排列组合问题的不同之处,这两者需要达到一定标准,如path内元素个数达到一定值才可添加进res),当搜索的深度达到最大长度时,即回溯。
2)更妙的方法
记原序列中元素的总数为 nn。原序列中的每个数字的状态可能有两种,即「在子集中」和「不在子集中」。我们用 11 表示「在子集中」,00 表示不在子集中,那么每一个子集可以对应一个长度为 nn 的 0/10/1 序列。例如,n = 3n=3 ,a = \{ 5, 2, 9 \}a={5,2,9} 时:(参考:力扣)
(3)代码如下(回溯):
class Solution24 {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res=new ArrayList<>();
List<Integer> path=new ArrayList<>();
Arrays.sort(nums);
int len=nums.length;
if(len==0){
return res;
}
//begin:下一轮开始搜索的位置
//len:数组总长度
dfs(nums,0,path,res,len);
return res;
}
public void dfs(int[] nums,int begin,List<Integer> path,List<List<Integer>> res,int len){
res.add(new ArrayList<>(path));
/*if(begin==len){
return;
}*/ //这一步有些多此一举,若begin=len时,回溯算法还是会回退到上一步,因为循环进不去
for (int i = begin; i < len; i++) {
path.add(nums[i]);
dfs(nums,i+1,path,res,len);
//递归退出时则返回执行递归前的各种状态
path.remove(path.size()-1);
}
}
}