LeetCode | 78. 子集

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [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) {
        vector<vector<int>>ret;
        ret.push_back({});//压入空集
        int size = nums.size();
        int subsize = pow(2,size);
        int hash = 1;
        while(hash < subsize){
            vector<int>temp;
            for(int k = 0;k<size;++k){
                int a = 1<<k;
                if(a&hash){
                    temp.push_back(nums[k]);
                }
            }
            ret.push_back(temp);
            ++hash;
        }
        return ret;
    }
};

原理:

数组元素个数 为 3 ,那么 全部子集有 $2^3 = 8 $个, 使用位图表示,其中 位为 1 表示数组下标对应的位置。

0 0 0 => { } //但要注意一下,这里我们是以 a = 1 << k 的所以并不会直接压空集进集合中

0 0 1 => { 1 }

0 1 0 => { 2 }

0 1 1 => { 1, 2}

1 0 0 => { 3 }

1 0 1 =>{1 , 3}

1 1 0 => {2 , 3}

1 1 1 =>

递归解法:

class Solution {
public:
    vector<vector<int>> result;
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<int> tmp(nums.size(), 0);
        subsets(nums, tmp, 0, 0);
        return result;
    }

    void subsets(vector<int>& nums, vector<int>& tmp, int pos, int t_pos) {
        if (pos >= nums.size()) {
            result.emplace_back(vector<int>(tmp.begin(), tmp.begin()+t_pos));
            return;
        }
        tmp[t_pos] = nums[pos];
        subsets(nums, tmp, pos + 1, t_pos+1);  // 取nums[pos]
        subsets(nums, tmp, pos + 1, t_pos);    // 不取nums[pos]
    }
};

回溯解法:

/*
to be continue;
*/
posted @ 2020-04-03 10:12  RioTian  阅读(119)  评论(0编辑  收藏  举报