「leetcode」78.子集

image

原題

給定一組不含重複元素的整數數組 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
…… …… ……

代碼

解答1

假設參數數組的長度爲4。咱們該怎麼獲取子集的數量呢?咱們由上面👆的思路可知,若是數組長度爲4,那麼集合的數量就爲0b1111io

/**
 * @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
};

解答2

/**
 * @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
};
相關文章
相關標籤/搜索