两种方法:回溯法 和 位运算法
1.回溯法
nums=[1 2 3]
它的子集的组成就是:要么有1,要么没有1;要么有2,要么没2;要么有3,要么没有3
所以从1开始,分成了两条支线:有1,没有1,然后有1的情况,又继续分为有2和没有2……
可以用递归来解决
class Solution { public: //回溯 void subset(int i,vector<int>& nums, vector<int>& tmp, vector<vector<int>>& res) { if(i>=nums.size()) return; tmp.push_back(nums[i]); res.push_back(tmp); subset(i+1,nums,tmp,res); tmp.pop_back(); subset(i+1,nums,tmp,res); } vector<vector<int>> subsets(vector<int>& nums) { vector<vector<int>> res; if(nums.size()==0) return res; vector<int> tmp; res.push_back(tmp);//空子集 subset(0,nums,tmp,res); return res; } };
方法2:位运算法
nums = [1,2,3],子集有2^3=8个
用1来表示子集有nums中的某个数,0表示没有这个数。第1个数 就表示成100,第2个数 就表示成010,第3个数就表示成 001……
nums的子集有:
[] ,空集,就相当于是 000,然后与第一个数 运算 000&100 = 0,就说明没有第一个数,后面类似
再比如子集 【1,3】就写成101,与第一个数按位与,101&100 = 1,所以这个子集有nums的第一个数,与nums的第二个数按位与 101&010 = 0,所以这个子集就没有nums的第2个数
所以可以遍历nums的子集,从0——2^n-1,然后每个子集依次与nums的每个数按位与,判断这个子集有没有这个数,有的话就push_back
class Solution { public: vector<vector<int>> subsets(vector<int>& nums) { //方法2,位运算法 vector<vector<int>>res; if(nums.size() == 0) return res; int all_subsets = 1<<nums.size();//一共有2^n个子集 for(int i =0;i<all_subsets;++i) { vector<int>tmp; for(int j = 0;j<nums.size();++j) { if(i & (1<<j) )//如果nums中的第j个数在i所表示的子集中 { tmp.push_back(nums[j]); } } res.push_back(tmp); } return res; } };