「前端刷题」78. 子集

115 阅读1分钟

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战」。

题目

链接:leetcode-cn.com/problems/su…

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

 

示例 1:

**输入:**nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

**输入:**nums = [0] 输出:[[],[0]]

 

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10
  • nums 中的所有元素 互不相同

解题思路

  1. 迭代

依次把每个元素插入到之前的集合中生成新的结果集合

  • 时间复杂度: O(n*2^n)
  • 空间复杂度: O(n*2^n)
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsets = function (nums) {
  const res = [[]];

  for (let i = 0; i < nums.length; i++) {
    const t = [];
    for (let j = 0; j < res.length; j++) {
      t.push([...res[j], nums[i]]);
    }

    res.push(...t);
  }

  return res;
};
  1. 回溯

每个元素都有两个状态,递归分别尝试两种状态的结果。所以时间复杂度是 O(2^n)

  • 时间复杂度: O(2^n)
  • 空间复杂度: O(n * 2^n)
var subsets = function (nums) {
  const res = [[]];
  const divide = (arr, index) => {
    if (index >= nums.length) {
      return;
    }

    const t = [...arr, nums[index]];
    res.push(t);
    divide(t, index + 1);

    divide(arr, index + 1);
  };

  divide([], 0);

  return res;
};
  1. 位运算

每个数字都有两种状态,和二进制是保持一致的,所以有 2^n 个解,把每个数字都转换成二进制。再根据二进制每位上的 1 来表示存在。

额外计算了二进制,效率会比其他方法差一些

  • 时间复杂度: O(n * 2^n)
  • 空间复杂度: O(n * 2^n)
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsets = function (nums) {
  const res = [];

  for (let i = Math.pow(2, nums.length) - 1; i >= 0; i--) {
    const str = i.toString(2);
    const t = [];

    for (let j = 0; j < str.length; j++) {
      if (str.charAt(j) === "1") {
        t.push(nums[j + (nums.length - str.length)]);
      }
    }

    res.push(t);
  }

  return res;
};
  1. 其他 这里相比之前几道类似的题,res处不用条件 因为题意是,所有可能的子集,连 [ ] 都不放过 且当前自增变量不能传递下去,要传递下一个自增变量 i + 1 因为并没有说可以重复利用原数组的单个元素去组合子集,所以下一次搜索要从 i + 1 开始,跳过当前元素
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsets = function(nums) {
    let n = nums.length;
    let tmpPath = [];
    let res = [];
    let backtrack = (tmpPath,start) => {
        res.push(tmpPath);
       for(let i = start;i < n;i++){
           tmpPath.push(nums[i]);
           backtrack(tmpPath.slice(),i+1);
           tmpPath.pop();
       } 
    }
    backtrack(tmpPath,0);
    return res;
};

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsets = function(nums) {
    var result = [];
    var subsets = [];
    var index = 0;
    var len = nums.length;
    function combinate(subsets,index){
         // terminator
        if(index == len){
            result.push(subsets)
            return;
        }
        // process
        combinate(subsets,index+1);
        subsets.push(nums[index]);
        combinate(subsets.slice(0),index+1);
        // reverse states
        subsets.pop();

        //或
        // process
        // combinate(subsets.slice(0),index+1);
        // subsets.push(nums[index]);
        // combinate(subsets.slice(0),index+1);
    }
    combinate(subsets,0);
    return result;
};