题目地址: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(); } };