78:子集(C++)

题目地址:https://leetcode-cn.com/problems/subsets/

题目描述

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

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

题目示例

示例:

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

解题思路

思路1:动态规划。我们使用二维数组进行存储,首先存储数组nums中的每个元素自身,然后以该元素为起点,分别遍历查找nums数组其它元素,最后将其加入到结果集中。以[1,2,3]为例,首先往res中添加空集,即[]。然后当循环第一次的时候,二维数组为空,此时,往结果集res中存放元素[1],即nums[0],现在res中相当于有了两个子集,即[],[1];循环第二次的时候,即要将nums[1]存放到前面的所有子集中,可以发现,res[0]是为空的,所以将nums[1]加入到res[0]的集合中,即[2]等价于[[],[2]];而res[1]是存在元素的,值为1,此时需要将nums[1]=2加入到res[1]集合中,从而构成子集[1,2];到次为止,res中拥有的子集为[],[1],[2],[1,2];接下来就是将nums[2]存放到所有的子集中,类似于上述流程,构成子集[3],[1,3],[2,3],[1,2,3];到目前为止,res中的子集全部结束,结果为[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]。

思路2:递归求解。我们可以发现,当数组nums的元素为n时,其子集的数目为2^n个,而每个子集可以看作是对数组nums中的每个元素是否添加的过程,即选不选的问题,如果选,则把它加入进来,然后将所维护的数组元素减少一个;如果不选,则维护的数组不变。

程序源码

思路1

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        if(nums.empty()) return res;
        res.push_back({});
        // 当前加入的元素值为nums[i]
        for(int i= 0; i < nums.size(); i++)
        {
            int len = res.size(); // 前面i-1个子集中的元素个数
            // 将nums[i]分别放入res[j]的各个vect中,再放进res中
            for(int j = 0; j < len; ++j)
            {
                // 将nums[i]放入空集中
                if(res[j].empty()) res.push_back({nums[i]});
                else{
                    vector<int> temp;
                    temp = res[j];
                    temp.push_back(nums[i]);
                    res.push_back(temp);
                }
            }
        }

        return res;
    }
};

思路2

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res; //结果集
        vector<int> list; //维护nums数组元素
        if(nums.empty()) return res;
        dfs(res, nums, list, 0);
        return res;
    }
    void dfs(vector<vector<int>>& res, vector<int>& nums, vector<int>& list, int index)
    {
        //递归终止条件
        if(index == nums.size())
        {
            res.push_back(list);
            return;
        }
        //递归求解,即处理当前层
        dfs(res, nums, list, index + 1); //不选该数,使得list不变

        list.push_back(nums[index]);
        dfs(res, nums, list, index + 1); //选择该数
        //清扫当前层的状态
        list.pop_back();
    }
};
----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
原文地址:https://www.cnblogs.com/wzw0625/p/13543552.html