移位运算符解子集问题--用移位运算符转十进制为二进制

 想直接看十进制转二进制的同学可以跳转:

目录

p.用移位运算符转十进制为二进制

子集是一个数学概念:如果集合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,  结果等于

再将 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;
}

希望和诸君共勉!

猜你喜欢

转载自blog.csdn.net/qq_61567032/article/details/124545156