lintcode(17)——子集

博客主要围绕子集和子集 II 问题展开。子集问题要求给定含不同整数集合,返回所有子集;子集 II 问题则针对可能含重复数字的列表。两者都提出用递归与非递归方式解决的挑战,且都有子集元素非降序、解集无重复子集等注意事项。

17. 子集

给定一个含不同整数的集合,返回其所有的子集。

样例 1:

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

样例 2:

输入:[1,2,3]
输出:
[[3],[1],[2],[1,2,3],[1,3],[2,3],[1,2],[]]

挑战

你可以同时用递归与非递归的方式解决么?

注意事项

子集中的元素排列必须是非降序的,解集必须不包含重复的子集。

非递归:

class Solution {
public:
    vector<vector<int>> subsets(vector<int> &nums) 
    {
        // write your code here
        vector<vector<int>> result;
        vector<int> temp;
        result.push_back({});
        if(nums.size()==0)
        {
            return result;
        }
        temp.push_back(nums[0]);
        result.push_back(temp);
        for(int i=1;i<nums.size();i++)
        {
            int len=result.size();
            for(int j=0;j<len;j++)
            {
                temp=result[j];
                temp.push_back(nums[i]);
                sort(temp.begin(),temp.end());
                result.push_back(temp);
            } 
        }
        return result;
    }
};

递归: 

class Solution {
private:
    void helper(vector<vector<int> > &result,vector<int> &temp,vector<int> &nums,int index) 
    {
        result.push_back(temp);
        for (int i =index; i < nums.size(); i++) {
            temp.push_back(nums[i]);
            helper(result, temp, nums, i + 1);
            temp.pop_back();
        }
    }
    
 public:
    vector<vector<int> > subsets(vector<int> &nums) {
        vector<vector<int> > result;
        vector<int> temp;

        sort(nums.begin(), nums.end());
        helper(result, temp, nums, 0);

        return result;
    }
    
};

18. 子集 II

给定一个可能具有重复数字的列表,返回其所有可能的子集。

样例 1:

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

样例 2:

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

挑战

你可以同时用递归与非递归的方式解决么?

注意事项

  • 子集中的每个元素都是非降序的
  • 两个子集间的顺序是无关紧要的
  • 解集中不能包含重复子集

非递归: 

class Solution {
public:
    vector<vector<int>> subsetsWithDup(vector<int> &nums) {
        // write your code here
        vector<vector<int>> result;
        vector<int> temp;
        result.push_back({});
        if(nums.size()==0)
        {
            return result;
        }
        temp.push_back(nums[0]);
        result.push_back(temp);
        for(int i=1;i<nums.size();i++)
        {
            int len=result.size();
            for(int j=0;j<len;j++)
            {
                temp=result[j];
                temp.push_back(nums[i]);
                sort(temp.begin(),temp.end());
                int k;
                for(k=0;k<result.size();k++)
                {
                    if(result[k]==temp)  break;
                }
                if(k==result.size())
                {
                    result.push_back(temp);
                }
            } 
        }
        return result;
    }
};
class Solution {
public:
    vector<vector<int>> subsetsWithDup(vector<int> &nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> subsets = {{}};
        vector<int> indexes = {-1}; // 记录subsets中每个集合结尾元素的下标
        for (int i = 0; i < nums.size(); ++i) {
            int size = subsets.size();
            for (int s = 0; s < size; ++s) {
                if (i > 0 && nums[i] == nums[i-1] && indexes[s] != i-1) {
                    continue;  // 去重,如果有重复数字出现,只有前上一个数字选了才能选当前数字
                }
                subsets.push_back(subsets[s]);
                subsets.back().push_back(nums[i]); //在subset的末尾元素中加入nums[i]
                indexes.push_back(i);
            }
        }
        return subsets;
    }
};

 

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值