「前端刷题」90. 子集 II

108 阅读1分钟

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

题目

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

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10

解题思路

思路1

大体思路,用图表示吧。。。。
如果没有重复元素,假设nums=[1,2,3,4]
[],
[1],(令[]内加上1这个元素)
[2],[1,2],(令[]和[1]内分别加上2这个元素)
[3],[1,3],[2,3],[1,2,3],(令[]和[1]和[2],[1,2]内分别加上3这个元素)
[4],[1,4],[2,4],[1,2,4],[3,4],[1,3,4],[2,3,4],[1,2,3,4](这个就不用我多说了叭)
遍历nums,使当前元素加入到之前的每一个子数组中组成新的子数组。

如果有重复元素,假设nums=[1,2,2,2,3]
[],
[1],
[2],[1,2],
[2,2],[1,2,2],(重复部分啦!这个就不是从[]到[1,2]都再加上2这个元素了!而是只有[2],[1,2]分别加上2这个元素)
[2,2,2],[1,2,2,2],(还是重复部分!仍然不是从头开始!而是只有[2,2],[1,2,2]分别加上2这个元素)
[3],[1,3],[2,3],[1,2,3],[2,2,3],[1,2,2,3],[2,2,2,3],[1,2,2,2,3](非重复部分,从头开始加!)

代码如下:

var subsetsWithDup = function(nums) {
    if (nums.length==0){
        return [nums];
    }
    if (nums.length==1){
        return [[],nums];
    }
    nums.sort((a,b)=>a-b);//先排序
    let result=[[]];//记录全部子数组
    let lastLength=0;//记录上一个元素添加前,result的长度
    for (let i=0;i<nums.length;i++){
        let j=0;
        if (i>0&&nums[i]==nums[i-1]){//当遇到重复元素时,从上一个元素添加前,result的长度处,开始每一个子数组都添加该元素
            j=lastLength;
        }
        let n=result.length;
        lastLength=result.length;//保持lastLength的更新
        for (;j<n;j++){//如果不是重复元素,j初始为0,从result开头,每个子数组都添加上该元素
            result.push([...result[j],nums[i]])
        }
    }
    return result;
};

思路2

  1. 数组排序,就可以从前往后取的时候,去重
  2. 循环,取数组的 1 - 数组长度的解
  3. 定义基准方法,获取长度为1的直接去重返回
  4. 长度不为1就递归

代码

function fn(arr, n) {
    let res = [];
    if (n === 1) {
      new Set(arr).forEach((e) => {
        res.push([e]);
      });
      return res;
    }
    // 记住开头的数组,防重复
    let map = [];
    for (let i = 0; i < arr.length; i++) {
      let num = arr[i];
      if (n - 1 <= arr.length - i - 1) {
        if (!map.includes(num)) {
          map.push(num);
          fn(arr.slice(i + 1), n - 1).forEach((e) => {
            res.push([num, ...e]);
          });
        }
      }
    }
    return res;
  }

  var subsetsWithDup = function (nums) {
    nums.sort((a, b) => a - b);
    const len = nums.length;
    let r = [[]];
    for (let i = 1; i <= len; i++) {
      r = r.concat(fn(nums, i));
    }
    return r;
  };