算法题(125):子集
审题:
本题需要我们将题目给定数组的所有子集枚举起来
思路:
方法一:二进制枚举
枚举对象:0到1<<n -1的整形数据
枚举顺序:顺序
枚举方式:二进制枚举
在解释二进制枚举的方法之前,我们先看看0~8的数字的二进制有什么特点
如果我们将0值定义为该索引位置不选,1定义为该索引位置可选。那么此时对于数字0~7的二进制情况,我们发现恰好完成了子集的枚举。
例子解释:
比如对于0数字,0~2的索引位置值都为0,说明这是三个数字都不选的情况
对于1数字,0索引位置值为1,其他位置值为0,说明这是只选择索引为0的数字的情况
其他数字情况也是同理
疑问:我们需要的数字范围是多少才能完全覆盖所有子集情况?
范围是0到(1<<n) -1。
我们先以给定数据个数为3举例,我们发现当数为8时,二进制的倒数第四位就有1了,说明到7的时候已经完成了数据个数为3所有的遍历。而8就是由1左移3位得到的,7是由8-1得到的。也就是说最远的遍历边界就是(1<<n)-1
综上,解题思路如下:
首先将需要遍历到的数依次取出,然后根据这些数的不同二进制位数值情况对子集进行数据插入。
当前子集插入完成后将子集放入二维的结果数组中,全部插入完成就直接返回结果数组
解题:
vector<vector<int>> subsets(vector<int>& nums) { int n = nums.size(); vector<vector<int>> vv; //二进制枚举所有情况 for(int i = 0; i < (1<<n); i++) { vector<int> tmp; //对数的选择进行展开 for(int j = 0; j < n; j++) { //二进制值对应位置为1就插入子集 if(i>>j & 1) tmp.push_back(nums[j]); } vv.push_back(tmp); } return vv; }
78. 子集 - 力扣(LeetCode)