幂集。编写一种方法,返回某集合的所有子集。集合中不包含重复的元素。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
对于每个数字,可取可不取。对于这一点:cur.push_back(nums[i]);dfs(nums,i+1,res,cur);cur.pop_back();就可以保证每个数字要么取,要么不取。
但对于[1,1,1]这样的序列:
当我们取了第一个1:后面两个1的情况可能是零个1、一个1或者两个1,后面的情况先不需要考虑。这样组合起来一共是:[1]、[1,1]、[1,1,1]。
接下来再不取这第一个1的时候,后面两个1的情况还可能为零个1、一个1或两个1。这样组合起来是:[1]、[1,1]。
可以看到有两个子集:[1]、[1,1]重复了。
现在回头看一下我们取第一个1的情况:得到的结果:[1]、[1,1]、[1,1,1]。这实际正好是我们所需要的全部可能子集。
所以对于对第二个1进行dfs以及第三个1进行dfs时就可以直接跳过。(注意不是for循环中遍历到第二个1、第三个1时跳过,而是dfs(xxx,第二个1,xxx)和dfs(xxx,第三个1,xxx)的时候跳过)
对于相同的数字我们需要合并处理,所以处理前要从小到大排序。
当然实际这道题规定了集合中没有重复数字,简单的取/不取,循环即可。
class Solution { public: vector<vector<int>> subsets(vector<int>& nums) { sort(nums.begin(),nums.end()); vector<int>cur; vector<vector<int>> res; dfs(nums,0,res,cur); return res; } void dfs(const vector<int>& nums,int cur_pos,vector<vector<int>>& res,vector<int>& cur){ res.push_back(cur); for(int i=cur_pos;i<nums.size();++i){ if(i>cur_pos and nums[i]==nums[i-1]){ continue; } cur.push_back(nums[i]); dfs(nums,i+1,res,cur); cur.pop_back(); } } };
原文:https://www.cnblogs.com/FdWzy/p/12629694.html