leetcode 78.子集
题目描述
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
题目链接:https://leetcode-cn.com/problems/subsets/
位运算解法
1.对于含m个元素的集合,构造长为m的01串,1和0分别表示该位置对应的元素在集合中存在或不存在。
2.在上述01串的含义下,十进制数0~2^n-1的二进制数能不重不漏地表示n个元素的存在情况,每一个数都代表一个子集。
2.用(1<<nums.size())-1获取含m个1的数,再对从0到1<<nums.size()-1之间的每一个数进行枚举,当某个数对应二进制中某一位是1就把集合中对应位置上的元素添加到集合中。
3.例如样例中就要构造一个长为3的01串,枚举从(000)2 到(111)2之间的数i,000代表空集,001代表第1个元素(从右往左数)存在于当前集合,010表示第2个元素存在于当前集合,011代表第1,2个元素存在于当前集合。。。对于i
∈
\in
∈[0~(1<<nums.size())-1],用i&1<<x即可判断倒数第(x+1)个元素是否存在于当前集合。
样例的表格:
表格呈现了以上思路的具体过程,也可以从表格出发更直观地理解以上思路。

c++代码:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>>result;
int n=(1<<nums.size())-1; / /获取nums.size()个1二进制对应的十进制(注意加括号)
for(int i=0;i<=n;i++){
vector<int>item; / /定义当前的集合
int x=1,now=nums.size()-1; / /x=00...1用于判断最后一个元素即nums[now]是否存在
while(x<=n){
if((i&x)==x) item.push_back(nums[now]); / /(i&x)==x则对应元素存在,加入当前集合
x=x<<1; / /把“1”左移,用于检测元素存在与否
now--; / /x左移的过程中now--,使得“1”的位置与元素位置对应
}
result.push_back(item); / /添加当前的集合到结果中
}
return result;
}
};
本文介绍了一种使用位运算解决LeetCode 78题子集问题的方法,通过将01串与二进制数关联,实现对数组所有可能子集的有效生成。并提供了详细的C++代码实现。
973

被折叠的 条评论
为什么被折叠?



