想直接看十进制转二进制的同学可以跳转:
目录
子集是一个数学概念:如果集合A的任意一个元素都是集合B的元素,那么集合A称为集合B的子集。
--百度百科
现在给你一个数组,按任意顺序输出这个数组的子集(空集也算哟~)。
遇见这中题目最容易想的就是DFS:
1、从0开始设置数组的长度;
2、将数组长度固定,传入DFS函数,循环递归得出子集。
一般的写法很麻烦,小编今天整些花活,用移位运算符来写
关于移位运算符的详细介绍,我在这里就不多赘述了,大家在CSDN上一查便知。
众所周知:移位运算符只针对二进制数,例如:
3 的二进制数是 011 ,将它右移移位,即 3 >> 1; 得到 001 等于1,所以
3 >> 1 = 1;
p.用移位运算符转十进制为二进制
对于一个数组,根据这个数组的元素是否在当前子集的状态,我们可以定义为:
如果这个元素在子集当中,就这个元素的状态为1,否则为0,即对应于所有的子集,都有一个与数组长度相等的二进制串:如下表所示(图片来源于leetcode官方题解)
请大家仔细观察,假设数组为{1,2,3},长度为3,从0遍历到3,得到的数的二进制串为:
000
001
010
100
101
110
111
在长度上,这组二进制串的个数刚好等于长度为3的数组的子集个数,在元素内容上,按照上面所述的方法:每一个二进制串表示的数字都是原数组的子集,并且没有重复,例如:
110 表示数组{1,2},是原数组的子集;100表示数组{1},也是原数组的子集。由此看来:
这题的思路就非常简单了:
假设数组长度为n,for从0遍历到n, 再对应的求出每一个二进制串所表示的数字即可。
问题来了,我们得到的是0~n的整数,怎么获取对应的二进制串呢?或者说,怎么获取对应的二进制串所表达的信息--数字串呢?
移位运算符可以做到!
假设现在得到的数字是:3, 让 1 & 3, 结果等于1
再将 3 右移移位,得到1, 重复上面的操作,1 & 1, 得到 1
在将1 右移一位, 得到0, 1 & 0, 得到 0 ,
组合上面红色的数字,得到 011 ,恰好是 3 的二进制串。
总结规律:假设我们知道二进制串的长度k,和这个二进制串所表示的整数s,我们用while循环n次,保存每次得到的数字后将s右移一位,倒序即可得到这个整数所表示的二进制串。
上代码:
//子集
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>>ans;
int n = nums.size();
for (int i = 0; i < pow(2,n); i++)
{
vector<int>ret;
int flag = n - 1;
int k = i;
while (flag >= 0)
{
if (1 & k)
{
ret.push_back(nums[flag]);
}
flag--;
k = k >> 1;
}
ans.push_back(ret);
}
return ans;
}
int main()
{
vector<int>nums;
for (int i = 0; i < 3; i++)
{
int a = 0;
cin >> a;
nums.push_back(a);
}
vector<vector<int>>ans = subsets(nums);
for (int i = 0; i < ans.size(); i++)
{
for (int j = 0; j < ans[i].size(); j++)
{
cout << ans[i][j] << " ";
}
cout << endl;
}
return 0;
}
希望和诸君共勉!