题目描述
给定一组不含重复元素的整数数组 nums
,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
样例
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
算法1
枚举每个位置的数 选 还是 不选,并递归到下一层,当u == nums.length
时,表示有一种满足题意的情况看,加入到ans
链表中
时间复杂度 $O(2^n)$
Java 代码
class Solution {
static List<List<Integer>> ans = new ArrayList<List<Integer>>();
static List<Integer> path = new ArrayList<Integer>();
static void dfs(int[] nums,int u)
{
if(u == nums.length)
{
ans.add(new ArrayList(path));
return ;
}
//选
path.add(nums[u]);
dfs(nums,u + 1);
path.remove(path.size() - 1);
//不选
dfs(nums,u + 1);
}
public List<List<Integer>> subsets(int[] nums) {
ans.clear();
dfs(nums,0);
return ans;
}
}
算法2
二进制
由于每个数有选和不选两种情况,因此总共有 2^n
种情况,用二进制 0
到 2^n
表示所有的情况,在某种情况i
中,若该二进制i
的第j
位是1
,则表示第j
位这个数选,加入到path
中,枚举完i
这种情况,将path
加入到ans
链表中
时间复杂度 $O(2^n n)$
Java 代码
class Solution {
static List<List<Integer>> ans = new ArrayList<List<Integer>>();
static List<Integer> path = new ArrayList<Integer>();
public List<List<Integer>> subsets(int[] nums) {
ans.clear();
int n = nums.length;
for(int i = 0;i < 1 << n;i ++)
{
path.clear();
for(int j = 0;j < n;j ++)
{
if((i >> j & 1) == 0)
path.add(nums[j]);
}
ans.add(new ArrayList<Integer>(path));
}
return ans;
}
}
==0 写错了应该是==1 把