题意:
        给定一个整数数组 nums ,其中可能包含重复元素,请你返回这个数组的所有可能子集。
        返回的答案中不能包含重复的子集,将答案按字典序进行排序


方法一:
递归+剪枝

思路:
         递归回溯题型,先画图再写代码。
        
        得到的每棵子树都是集合的子树。
        
        注意:这里要剪枝,当前一个数等于当前数并且前一个数未访问过,则跳过该分支。
        
if(i>0&&nums[i]==nums[i-1]&&vis[i-1]==0)//剪枝
    continue;




class Solution {
public:
    vector<vector<int>> res;
    int vis[15]={0};
    vector<vector<int>> subsets(vector<int>& nums) {
        sort(nums.begin(),nums.end());//排序
        vector<int> v;
        dfs(nums,0,v);//递归
        return res;
    }
    
    void dfs(vector<int>& nums,int st,vector<int> &v){
        res.push_back(v);//加入结果二维数组
        int n=nums.size();
        for(int i=st;i<n;i++){
            if(i>0&&nums[i]==nums[i-1]&&vis[i-1]==0)//剪枝
                continue;
            v.push_back(nums[i]);
            vis[i]=1;
            dfs(nums,i+1,v);//递归回溯
            v.pop_back();
            vis[i]=0;
        }
    }
};

时间复杂度:
空间复杂度:

方法二:
暴力递归(非剪枝)

思路:
        暴力递归。
        利用一个无序set实现去重效果,忽略剪枝。


class Solution {
public:
    vector<vector<int>> res;
    int vis[15]={0};
    unordered_set<string> mySet;//无序set
    vector<vector<int>> subsets(vector<int>& nums) {
        sort(nums.begin(),nums.end());//排序
        vector<int> v;
        dfs(nums,0,v);//递归
        return res;
    }
    
    void dfs(vector<int>& nums,int st,vector<int> &v){
        
        string str="";
        for(int i=0;i<v.size();i++){
            str+=v[i]+'0';
        }
//         cout << str << endl;
        if(mySet.count(str)==0){//实现去重
            res.push_back(v);//加入结果二维数组
            mySet.insert(str);
        }
        
        int n=nums.size();
        for(int i=st;i<n;i++){
            v.push_back(nums[i]);
            vis[i]=1;
            dfs(nums,i+1,v);//递归回溯
            v.pop_back();
            vis[i]=0;
        }
    }
};

时间复杂度:
空间复杂度: