[LeetCode78] Subsets
题目:求数组子集
Given a set of distinct integers, nums, return all possible subsets.
Note: The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,3], a solution is:
[ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
分类:Array Backtracking Bit Manipulation
代码:
第一种:
class Solution { public: //基于同质的递归 //比如要求{1, 2, 3}的所有子集,可以先求{2, 3}的所有子集, //{2, 3}的子集同时也是{1, 2, 3} 的子集,然后我们把{2, 3}的所有子集都加上元素1 vector<vector<int>> subsets(vector<int>& nums) { vector<vector<int>> res; res.push_back(vector<int>()); if (nums.empty()) return res; for (int i = 0; i < nums.size(); ++i) { vector<vector<int>> tmpVec = res; for (auto v : tmpVec) { vector<int> tmp(v); v.push_back(nums[i]); res.push_back(v); } } return res; } };
第二种:
原数组中每一个元素在子集中有两种状态:要么存在、要么不存在。这样构造子集的过程中每个元素就有两种选择方法:选择、不选择,因此可以构造一颗二叉树来表示所有的选择状态:二叉树中的第i+1层第0层无节点表示子集中加入或不加入第i个元素,左子树表示加入,右子树表示不加入。所有叶节点即为所求子集。因此可以采用DFS的递归思想求得所有叶节点。
1 //S为原数组,temp为当前子集,level为原数组中的元素下标亦为二叉树的层数,result为所求子集集合 2 void subsets(vector<int> &S,vector<int> temp,int level,vector<vector<int> > &result) 3 { 4 //如果是叶子节点则加入到result中 5 if(level == S.size()) 6 { 7 result.push_back(temp); 8 return; 9 } 10 //对于非叶子节点,不将当前元素加入到temp中 11 subsets(S,temp,level + 1,result); 12 //将元素加入到temp中 13 temp.push_back(S[level]); 14 subsets(S,temp,level + 1,result); 15 }
第三种:
求子集问题就是求组合问题。数组中的n个数可以用n个二进制位表示,当某一位为1表示选择对应的数,为0表示不选择对应的数。
1 vector<vector<int> > subsets(vector<int> &S,int n) 2 { 3 //n个数有0~max-1即2^n中组合,1<<n表示2^n 4 int max = 1<<n; 5 vector<vector<int> >result; 6 for(int i = 0;i < max;i++) 7 { 8 vector<int> temp; 9 int idx = 0; 10 int j = i; 11 while(j > 0) 12 { 13 //判断最后一位是否为1,若为1则将对应数加入到当前组合中 14 if(j&1) 15 { 16 temp.push_back(S[idx]); 17 } 18 idx++; 19 //判断了这一位是否为1后要右移 20 j = j>>1; 21 } 22 //判断完了一种组合,加入到结果集中 23 result.push_back(temp); 24 } 25 return result; 26 }

浙公网安备 33010602011771号