【LeetCode】90. Subsets II解法及注释

90. Subsets II

Total Accepted: 65104 Total Submissions: 214320 Difficulty: Medium

Given a collection of integers that might contain duplicates, nums, return all possible subsets.

Note:

  • Elements in a subset must be in non-descending order.
  • The solution set must not contain duplicate subsets.

For example,
If nums = [1,2,2], a solution is:

[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]



【分析】

     这个题我思考了很久,感觉并没有非常好的解法,首先有几个回避不了的问题:

     1、题目要求所有子集中的数据非降序排列,如此,对输入数据集进行排序不可避免,sort()可以解决,时间复杂度O(nlogn);

     2、要求所有子集,以一个N个元素的数据集为例,其可能的子集数为:N(N+1)/2  +空集,因此,最差搜索时间复杂度O(n2);

     3、出现重复数据,如何去重复?

     思考良久,我还是采用了深度优先搜索(Deepth First Search,DFS),DFS方法可以搜索到指定深度的所有可行解。若不考虑空集,此题的深度范围[1,N],因此需要比普通的DFS增加一重循环;同时,考虑到去重复,需要在搜索过程中“剪枝”,这也是解决此题的关键,我简单叙述一下DFS中去重复(“剪枝”)的方法:对于一个数据集[1,2,2,2],如果深度为3(须三层搜索),即三个元素的子集,由于DFS本身结合递归和回溯的思想,对于任何一层搜索,若不考虑重复数据,则决不能出现重复数据,如:第二层第一次搜索得元素2,那么搜索到底回溯至第二层时,理论上应该对第二层进行第二次搜索,得元素2,但是这样明显重复了,为什么会重复呢?因为DFS每一层搜索事实上都是一种“穷举”的思想,因此,必须剪枝。


【解法及注释】

class Solution {
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) 
    {
        
        vector<vector<int>> result;
        vector<int> temp;
        if(nums.empty())return result;
        sort(nums.begin(),nums.end());
        
        result.push_back(temp);//存入空集
        
        for(int i=1;i<=nums.size();i++)//深度搜索,深度分别为[1,N]
        {
            DFS(nums, result, temp, i,0);
        }
        return result;
        
    }
private:
    
    
    void DFS(vector<int>& nums,vector<vector<int>>& result,vector<int>& temp,int deepth,int start)
    {
        if(temp.size()==deepth)//搜索深度到达,存储可行解,返回上一层继续搜索
        {
            result.push_back(temp);
            return;
        }
        else
        {
            for(int i=start;i<nums.size();i++)
            {
                if(i!=start&&nums[i]==nums[i-1])continue;//剪枝去重复,对于搜索的任何一层决不能在本层出现重复
                
                temp.push_back(nums[i]);//存储到可行解路径中
                DFS(nums, result, temp, deepth,i+1);//搜索下一层,注意其搜索起点i+1,避免数据重复使用
                temp.pop_back();//某一层搜索结束顶层出栈,或者某一层数据搜索到可行解,继续该层下一次搜索
            }
        }
    }
};



【运行结果】

          


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jin_Kwok

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值