# 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)$