---
# System prepended metadata

title: 0078. Subsets
tags: [Leetcode, DFS, 回溯, Medium]

---

#    0078. Subsets
###### tags: `Leetcode` `Medium` `回溯` `DFS`
Link: https://leetcode.com/problems/subsets/


## Code
### 方法一
直接遍历，初始状态是只有一个子集是空集合，遇到一个数就把所有子集加上该数组成新的子集，遍历完毕即是所有子集
```java=
class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        int len = nums.length;
        List<List<Integer>> res = new ArrayList<>();
        res.add(new ArrayList<>());
        for (int i = 0; i < len; i++) {
            for (int j = res.size() - 1; j >= 0; j--) {
                ArrayList<Integer> tmp = new ArrayList<>((ArrayList<Integer>) res.get(j));
                tmp.add(nums[i]);
                res.add(tmp);
            }
        }
        return res;
    }
}
```
### 方法二：回溯
#### 回溯一
```java=
class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        int len = nums.length;
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> ele = new ArrayList<>();
        dfsSubsets(res, 0, len, nums, ele);
        return res;
    }

    private void dfsSubsets(List<List<Integer>> res, int index, int len, int[] nums, List<Integer> ele) {
        res.add(new ArrayList<>(ele));
        for (int i = index; i < len; i++) {
            ele.add(nums[i]);
            dfsSubsets(res, i + 1, len, nums, ele);
            ele.remove(ele.size() - 1);
        }
    }

}
```
#### 回溯二
```java=
class Solution {

    public List<List<Integer>> subsets(int[] nums) {
        int len = nums.length;
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> ele = new ArrayList<>();
        res.add(new ArrayList<>());
        dfsSubsets(res, 0, len, nums, ele);
        return res;
    }
    private void dfsSubsets(List<List<Integer>> res, int index, int len, int[] nums, List<Integer> ele) {
        if (index == len) return;
        for (int i = index; i < len; i++) {
            ele.add(nums[i]);
            res.add(new ArrayList<>(ele));
            dfsSubsets(res, i + 1, len, nums, ele);
            ele.remove(ele.size() - 1);
        }
    }
}
```

### 方法三：二进制数

Lexicographic (Binary Sorted) Subsets 很巧妙的方法
建立一个和nums一样大小的阵列，里面只放0跟1，1代表这个位置对应的nums这个位置的值，要被放在现有的subset里面，0代表不放。（The idea is that we map each subset to a bitmask of length n, where 1 on the ith position in bitmask means the presence of nums[i] in the subset, and 0 means its absence.）
那么现在我们只要产生00.....00到11...11的数，这里需要注意，因为**要有left zero padding**
这个方法没有用c++写的原因是它很难建立这样的阵列
```c
    bitset<nums.size()> binary_num (i);
    string bitmask = binary_num.to_string();
```
bitset后面的<>里面必须放整数，不能放变量，即使是用```const int n = nums.size()```也不行。

$n=3$，全集${3,2,4}$

二进制数 | 子集
-------|-----
 000   | {} 
 001   | {3}
 010   | {2}
 011   | {3,2}
 100   | {4}
 101   | {4,3} 
 110   | {4,2}
 111   | {3,2,4}
 
```java=
class Solution {
    List<Integer> t = new ArrayList<Integer>();
    List<List<Integer>> ans = new ArrayList<List<Integer>>();

    public List<List<Integer>> subsets(int[] nums) {
        int n = nums.length;
        for (int mask = 0; mask < (1 << n); ++mask) {
            t.clear();
            for (int i = 0; i < n; ++i) {
                if ((mask & (1 << i)) != 0) {
                    t.add(nums[i]);
                }
            }
            ans.add(new ArrayList<Integer>(t));
        }
        return ans;
    }
}
```
时间复杂度$O(n\cdot 2^n)$
空间复杂度$O(n)$