Loading

Leetcode每日一题 90.子集 II

90. 子集 II

给你一个整数数组 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

本题用回溯算法比较容易理解

class Solution {
public:
    vector<vector<int>> res;
    vector<int> sub;
    int size;
public:
    void back(vector<int>& nums,int start)
    {
        res.push_back(sub);
        for(int i = start ; i < size ; i++)
        {
            if(i > start && nums[i] == nums[i-1])
                continue;
            sub.push_back(nums[i]);
            back(nums,i+1);
            sub.pop_back();
        }
    }
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
       res.clear();
       sub.clear();
       this->size = nums.size();
       sort(nums.begin(),nums.end());
       back(nums,0);

       return res;
    }
};

首先将nums排序,因为这样才能达到去重的目的,后面说。
start是每次组合的首地址,直接看循环,分析if为什么这样写


设置i>start是为了防止第一次循环就判断nums[i] == nums[i-1],这不是我们要判断的范围,因为i==start时,明显我们只有一个元素进来。
nums[i] == nums[i-1] 是为了去重,有点不好解释,我们就这样想象,举个例子[1,2,3,3],start是0的时候我们从1进入,然后递归进入back(),不管它子递归的循环,我们就只看第一次递归的循环,是不是会得到[1,2,3,3],你们可能会说,你不是设置了nums[i] == nums[i-1]就continue吗,为什么会得到[1,2,3,3],这就是因为前面有个i>start,但如果我们在子循环时,也就是此时sub里面有[1,2]时的递归层,我们遍历到第一个3,加进去sub = [1,2,3],此时i明显已经大于start,我们不会再得到第二个[1,2,3],此时这个3是第4个3.


用一个非常妙的解释方法就是,把整个结构想象成一个树,层相同是不允许的,树枝相同是允许的。

i > start && nums[i] == nums[i-1]就诠释了这种判断。

posted @ 2021-03-31 23:52  eveilcoo  阅读(59)  评论(0编辑  收藏  举报