假设有一个list [1,2,3],要求出list的所有子集!
假设一个list的长度为n,那么它就包含 个子集(包含空集)。同样的,1个长度为 n 的二进制字符串,可以表示 个数。
所以我们不难联想到,要求list的子集,其实就是位运算:
[ ] ——> 0 0 0 ——> 0
[1] ——> 1 0 0 ——> 4
[2] ——> 0 1 0 ——> 2
[3] ——> 0 0 1 ——> 1
[1,2] ——> 1 1 0 ——> 6
[1,3] ——> 1 0 1 ——> 5
[2,3] ——> 0 1 1 ——> 3
[1,2,3] ——> 1 1 1 ——> 7
所以要得到长度为 n 的list的子集,只需要遍历从 0—-1 ,然后转化成二进制,把对应位置为 1 的数字放入集合。
十进制转二进制:
因为我使用的是Java,在Java中有现成的语句能够调用:
int a = 8
b = Integer.toBinaryString(a);
输出:b = "1000"
当然也可以按照二进制的定义自己写:
public int toBinary(int num) {
int r = 0;
int k = 1;
int sum = 0;
while(num != 0) {
r = num % 2;
sum += r*k;
k *= 10;
num /= 2;
}
return sum;
}
完整代码(Java):
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> sets = new ArrayList<List<Integer>>();
for(int i=0;i<=Math.pow(2, nums.length)-1;i++) {
List<Integer> list = new ArrayList<Integer>();
String a = Integer.toBinaryString(i); //转化为二进制
for(int j=0;j<a.length();j++) {
char c = a.charAt(j); //取到String中的每个字符
if(c == '1') list.add(nums[nums.length-a.length()+j]); //把对应位置为1的数字放入集合
}
sets.add(list);
}
return sets;
}