题目链接
题目描述
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
题目示例
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
输入:nums = [0]
输出:[[],[0]]
题目提示
- 1 <= nums.length <= 10
- -10 <= nums[i] <= 10
- nums 中的所有元素 互不相同
题目思路
给定数组nums中的元素在子集中有两种不同的状态——存在和不存在,因此我们可以使用一个整形数组,整形数组中每一位代表nums中每一个元素的状态,如果是0代表对应的nums中的数不存在,如果是1代表对应的nums中的数存在
例如nums中有1, 2, 3这三个元素,那么我们可以创建一个整形数组arr,arr一共有三个元素,arr[0]对应1,arr[1]对应2,arr[2]对应3
如果arr[0]是0,则组合1中“1”这个元素不存在,根据排列组合原则,我们可以知道一共存在2^(nums.length)个组合,如果有三个元素,那么就有8种组合
可以看出,这八种不同的组合就对应了我们二进制中的0到7,因此,我们可以通过0-7这几个数字,确定子集中包含的元素
定义一个变量i,for循环i从0开始到2,让1左移i位,判断和组合中的数字中的一位是否都是1,如果都是1,就把对应的元素添加到子集中
例如我们要添加子集(1,3),那么对应的arr就是101,对应的十进制数字就是5,我们定义一个i,初始是0
1 << i位,左移0位时 & 5 != 0,说明1应该添加在子集中,左移1位时 & 5 == 0,说明2不在子集中,左移2位时 & 5 != 0,说明3应该添加在子集中,最终,把存在1,3这个子集添加到List中
因此,依次将0-7都进行比较,就可以得到含所有子集的集合了
需要注意的是:
我们在比较时使用的是 (1 << i ) & 5 != 0时说明这个数应该存储在子集中,而不是 (1 << i ) & 5 == 1,这是因为如果i不等于0时,所得到的并不是1,而是1后面加(i - 1)个0对应的二进制数
例如(1 << 3)& 5 ,最终得到的结果是4
代码实现
class Solution {
public List<List<Integer>> subsets(int[] nums) {
int len = nums.length;
int n = (int) Math.pow(2,len);
List<List<Integer>> lists = new ArrayList<>();
for (int x = 0; x < n; x++) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < len; i++) {
if(((1 << i) & x) != 0){
list.add(nums[len - 1 - i]);
}
}
lists.add(list);
}
return lists;
}
}