子集 II

107 阅读1分钟

题目描述

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

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

示例1:

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

思路

  1. 本题与子集 思路一本一致,唯一不同点是多了去重的操作
  2. 本题的去重应该怎么来去呢?
  • 首先画出抽象树结构

image.png

  • 由上图我们可以知道去重逻辑为:nums[i]==nums[i-1]&&used[i-1]=false 前一个元素与本元素相等并且前一个元素在本轮选择中未被使用。
  • 很重要的点:数组必须是一个递增数组,也就是要排序

代码

function subsetsWithDup(nums: number[]): number[][] {
    let result=[],path=[],used=new Array(nums.length).fill(false);//结果数组,路径数组
    result.push([]);
    // 排序
    nums.sort((a,b)=>a-b);
    function backTracking(nums: number[],startIndex:number): void{
        //终止条件
        if(startIndex==nums.length){
            return;
        }

        for(let i=startIndex;i<nums.length;i++){

            // 去重逻辑
            if(i>0&&nums[i]==nums[i-1]&&!used[i-1]){
                continue;
            }
            path.push(nums[i]);
            used[i]=true
            result.push([...path]); //收割每层递归结果
            backTracking(nums,i+1);
            path.pop(); // 回溯操作
            used[i]=false;
        }
    }

    backTracking(nums,0)
    return result;
};

image.png

总结

本题是子集与组合总和思路的结合体,既有单层收割也有树层去重