题目:
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集不能包含重复的子集。你可以按任意顺序返回解集。
示例 1:
输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
此题有很多解法,但个人认为利用位运算比较好理解。针对不同的示例,我们可以得出这样的结论,即若数组nums的长度为n,则其子集一共有2 n ^{n} n个元素。由此我们联想到,是否可以通过编码即生成n位二进制数来为不同的子集元素进行编码呢?
000 | [ ] |
---|---|
001 | [3] |
010 | [2] |
011 | [2,3] |
100 | [1] |
101 | [1,3] |
110 | [1,2] |
111 | [1,2,3] |
显然我们需要两层for循环,第一层用来遍历000~111,第二层用来遍历每个二进制编码中哪一位是1,将是1的那一位所对应nums中的值放入子集元素中。我的代码中所有的这些操作都是用的位运算,1<<n
表示1左移n位即2
n
^{n}
n,1<<j
表示1左移j位即2
j
^{j}
j,但是j<n
,因为对于三位二进制假如要判断011哪一位有1只能将其分别与001(2
0
^{0}
0),010(2
1
^{1}
1)和100(2
2
^{2}
2)按位与。
class Solution {
public List<List<Integer>> subsets(int[] nums) {
int n=nums.length;
List<List<Integer>> sub=new ArrayList<>();
sub.add(new ArrayList<>());
for(int i=1;i<(1<<n);i++){
List<Integer> list=new ArrayList<>();
for(int j=0;j<n;j++){
if((i&(1<<j))>0)
list.add(nums[j]);
}
sub.add(list);
}
return sub;
}
}