给定一组不含重复元素的整数数组 nums,返回该数组全部可能的子集(幂集)。数组
说明:解集不能包含重复的子集。spa
示例:3d
输入: nums = [1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
使用位移和按位与的思路,来自leetcode的评论区。这个思路相对来讲比较抽象,下面是具体的解释。code
举一个例子🌰,nums = [a, b, c]
, 若是数组中全部的子项全都存在,咱们能够将其抽象成一个二进制数,111
(1表明数字存在)blog
子集 | 二进制数 |
---|---|
[] | 000 |
[a] | 100 |
[b,c] | 110 |
[a,c] | 101 |
[a,b,c] | 111 |
[b] | 010 |
[b,c] | 011 |
[c] | 001 |
111
的十进制数表示是7, 000
的十进制数表示是0,咱们只须要遍历从0到7的十进制数便可获得全部的子集。leetcode
如何将二进制数,反序列化为集合呢?咱们能够利用按位与&操做符。rem
举一个例子🌰。例如:110
表示[a,b]
, 咱们使用,110 & 100
等于1,表示a
存在。110 & 010
等于1,表示b
存在。110 & 001
等于0,表示c
不存在。it
子集 | A | B | C |
---|---|---|---|
[] | 000 & 100 === 0 | 000 & 010 === 0 | 000 & 001 === 0 |
[a] | 100 & 100 === 1 | 100 & 010 === 0 | 100 & 001 === 0 |
[b,c] | 110 & 100 === 1 | 110 & 010 === 1 | 110 & 001 === 0 |
…… | …… | …… |
假设参数数组的长度为4。咱们该怎么获取子集的数量呢?咱们由上面👆的思路可知,若是数组长度为4,那么集合的数量就为0b1111
。io
/** * @param {number[]} nums * @return {number[][]} */ var subsets = function(nums) { // 子集的数量 let len = '' const result = [[]] for (let i = 0; i < nums.length; i++) { len += '1' } // 获取最大的子集数量,[1, 2, 3]最大子集数量`0b111 === 7` len = parseInt(len, 2) for (let i = 1; i <= len; i++) { let temp = [] // 1 << 0 `0b001` // 1 << 1 `0b010` // 1 << 2 `0b100` // 判断每个位置是否存在 for (let j = 0; j < nums.length; j++) { if (i & (1 << j)) { temp.push(nums[j]) } } result.push(temp) } return result };
/** * @param {number[]} nums * @return {number[][]} */ var subsets = function(nums) { let result = [] for (let i = 0; i < nums.length; i++) { let temp = [] for (let j = 0; j < result.length; j++) { temp.push([...result[j], nums[i]]) } result = [...result, ...temp, [nums[i]]] } result = [...result, []] return result };