Given a set of distinct integers, nums, return all possible subsets (the power set)
Note: The solution set must not contain duplicate subsets
Example:
Input: nums = [1,2,3]
Output:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
注意:共 种可能的排列
1、迭代一
- 找出数组长度为1的所有解
- 再在长度为1的所有解上加一个不重复的数字得到长度为2的所有解
- 一直循环直到n
时间复杂度:
空间复杂度:
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res=new ArrayList<List<Integer>>();
List<List<Integer>> ans=new ArrayList<List<Integer>>();
ans.add(new ArrayList<Integer>());
res.add(new ArrayList<Integer>());
int n=nums.length;
//第一层循环,子数组长度从1到n
for(int i=1;i<=n;i++){
//第二层循环,遍历上次的所有结果
List<List<Integer>> tmp=new ArrayList<List<Integer>>();
for(List<Integer> list:res){
//第三次循环,对上次结果进行扩展
for(int m=0;m<n;m++){
//只添加比末尾数字大的数字,防止重复
if(list.size()>0 && list.get(list.size()-1)>=nums[m])
continue;
List<Integer> newList=new ArrayList<Integer> (list);
newList.add(nums[m]);
tmp.add(newList);
ans.add(newList);
}
}
res=tmp;
}
return ans;
}
2、迭代法2
求前k个元素的所有子数组,只需在前k-1个元素的所有子数组里加是nums[k]即可
- 考虑给定数组前1个元素的所有子数组
- 考虑给定数组前2个元素的所有子数组
- ........
- 考虑给定数组前n个元素的所有子数组
时间复杂度:
空间复杂度:
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
ans.add(new ArrayList<>());//初始化空数组
for(int i = 0;i<nums.length;i++){
List<List<Integer>> ans_tmp = new ArrayList<>();
//遍历之前的所有结果
for(List<Integer> list : ans){
List<Integer> tmp = new ArrayList<>(list);
tmp.add(nums[i]); //加入新增数字
ans_tmp.add(tmp);
}
ans.addAll(ans_tmp);
}
return ans;
}
3、回溯法
- 添加一个数
- 递归
- 删除之前的数
- 下次循环
时间复杂度:
空间复杂度:
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ans=new ArrayList<>();
getAns(nums,0,new ArrayList<>(),ans);
return ans;
}
private void getAns(int[] nums,int start,ArrayList<Integer>temp,List<List<Integer>> ans){
ans.add(new ArrayList<>(temp));
for(int i=start;i<nums.length;i++){
temp.add(nums[i]); //添加一个数
getAns(nums,i+1,temp,ans); //递归下一个数
temp.remove(temp.size()-1); //删除之前的数
}
}
}
4、位操作
- 数组每个元素有两个状态:在子数组/不在子数组
- 所有状态组合即所有子数组
- 遍历000到111
- 比特位为1将对应数组加入
1 2 3
0 0 0 -> [ ]
0 0 1 -> [ 3]
0 1 0 -> [ 2 ]
0 1 1 -> [ 2 3]
1 0 0 -> [1 ]
1 0 1 -> [1 3]
1 1 0 -> [1 2 ]
1 1 1 -> [1 2 3]
时间复杂度:
空间复杂度:
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ans=new ArrayList<>();
int bit_nums=nums.length;
int ans_nums=1<<bit_nums; //2的n次方-->所有解的个数
for(int i=0;i<ans_nums;i++){
List<Integer> tmp=new ArrayList<>();
int count=0; //记录当前对应数组的哪一位
int i_copy=i; //用来移位
while(i_copy!=0){
if((i_copy&1)==1){ //判断当前位是否是1
tmp.add(nums[count]);
}
count++;
i_copy=i_copy>>1; //右移一位
}
ans.add(tmp);
}
return ans;
}