求出所有可能的子集,就是要遍历一遍DFS递归树,把所有子集全都压入结果数组中。
class Solution { vector<vector<int>> res; vector<int> onePath; //onePath是递归树的一条路径(一个子集) public: vector<vector<int>> subsets(vector<int>& nums) { DFS(nums, 0); return res; } void DFS(vector<int>& nums, int depth) { //depth是当前递归的深度 res.push_back(onePath); //要求所有子集,所以把onePath压入res先 for(int i = depth; i < nums.size(); ++i) { //继续往深处搜索 onePath.push_back(nums[i]); DFS(nums, i + 1); onePath.pop_back(); //DFS回溯都是对称的,所以要恢复现场 } } };对于长度为n的数组,我们可以枚举所有长度为n的二进制串,并与数组元素进行与运算, 二进制串中的0表示子集不选这个数,1表示子集选这个数, 这样就直接枚举了所有的子集。
class Solution { public: vector<vector<int>> subsets(vector<int>& nums) { vector<vector<int>> res; for(int i = 0; i < 1 << nums.size(); ++i) { //枚举i从 0 ~ 2的nums.size()-1次方减一 vector<int> oneSubset; for(int j = 0; j < nums.size(); ++j) { //二进制串的长度是nums.size(),所以我们要逐位看看当前二进制串的各个位是0还是1(表示选还是不选) if((i >> j) & 1) { //判断i的二进制第j位是否为1,要把i右移j位与1做与运算 oneSubset.push_back(nums[j]); //如果是1,说明选第j个数,子集加上nums[j] } } res.push_back(oneSubset); //甭管现在子集是啥,肯定是原来没有的(每个二进制子串都不同),所以把子集加入res数组,安排! } return res; } };