一、题目
* 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 * 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 * 输入:nums = [1,2,3] * 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
二、思路
* 1 子集的数目用二进制来理解。如[1,2,3]中,000表示[],100表示[1],111表示[1,2,3] * 也就是说,二进制哪一位有1,对应数组的某个位置有数,也就是一个子集 * 2 因此,一个数组的子集,是2的幂次方个。如[1,2,3]有2^3=8个子集。 * 3 所以思路就是,给定数组,获取长度length,那么一共2^length个子集。 * 4 外层循环控制每一个子集,一共2^length层循环。 * 5 对于每一个子集,内层循环填充子集,填充个数最多为length,也就是内层循环length层 * 6 而内层循环要做的就是,依次拿0001,0010,0100,1000等,与外层循环的数按位与, * 按位与结果不为0说明外层循环的某一位为1,也就是要对应的填充到一维数组中。 * 7 举例子:[1,2]的子集为[],[1],[2],[12],对应的二进制依次为00,10,01,11, * 也就是2^2层外循环,对于外层循环的二进制10,内层循环中先用01按位与,结果为0,说明最低位不是1;再用10按位与,不为0,说明高位为1,那么就把[1,2]中的1添加进去,2不添加。
三、代码
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> resultList = new ArrayList<>();
for (int i = 1; i < Math.pow(2, nums.length); i++) { // 从1到2^10-1的每个数,分别输出一个一维数组
int j = 1; //j用来控制按位与的次数,
int flag = 1;
List<Integer> temp = new ArrayList<>();
while (j <= nums.length) { //循环的放一维数组
if ((flag & i) != 0) {
temp.add(nums[nums.length - j]);
}
flag <<= 1;
j++;
}
resultList.add(temp);
}
List<Integer> temp = new ArrayList<>();
resultList.add(temp);
return resultList;
}
}