在生成子序列时使用按位运算的逻辑是什么?

What is the logic to use bitwise operation in generating subsequences?

本文关键字:运算 是什么      更新时间:2023-10-16

我有一个数组,A=[1,2,3,4](其中n=4)。我想从这个数组生成子序列。 子序列数为 (2^n -1)

从计数器 0001 运行到 1111

for (int counter = 1; counter < 2^n; counter++)
{
for (int j = 0; j < n; j++)
{

检查计数器中的第 j 位是否已设置。如果设置,则从 arr[] 打印第 j 个元素

if (counter & (1<<j))
cout << arr[j] << " ";
}
cout << endl;
}
}

谁能解释我?它是如何工作的" 计数器 & (1<</div>

逻辑是这样的。比如说,就像你在例子中放的那样,你有n = 4,为了避免混淆,假设数组是A = [5, 7, 8, 9],例如。然后,您希望所有可能的序列都包含原始数组中的一些元素(至少一个)。所以你想要一个只包含第一个的序列,一个包含第一个和第二个的序列,第一个和第三个,等等。每个打印序列可能包含也可能不包含数组中的每个元素。所以你可以把它看作是这样的:

| 5 | 7 | 8 | 9 |    Sequence
-----------------    --------
| 1 | 0 | 0 | 0 | -> 5
| 1 | 1 | 0 | 0 | -> 5 7
| 1 | 0 | 1 | 0 | -> 5 8
...

也就是说,每个序列可以表示为一个位列表,每个位指示是否包含数组的每个成员。

在此循环中:

for (int counter = 1; counter < 2^n; counter++)

程序从1迭代到2^n - 1,在这种情况下15。因此,您获得的counter值为:

Dec  Binary
---  ------
1    0001
2    0010
3    0011
4    0100
5    0101
6    0110
7    0111
8    1000
9    1001
10    1010
11    1011
12    1100
13    1101
14    1110
15    1111

如果你仔细观察,你会发现我们有二进制的四个元素的所有可能的序列,由01组成(除了0000,这将是空序列,我们不感兴趣)。在此循环中:

for (int j = 0; j < n; j++)

程序只是遍历counter的每一点,从0(最右边)到n - 1,每当它找到一个1它就会输出相应的数组元素。条件:

if (counter & (1<<j))

简单地计算1<<j1加上j右边的零数(因此,例如,对于j = 0,它将是1,对于j = 2,它将是100),然后是按位和操作,因此它基本上仅"过滤"j位(例如1101 & 100 = 0100),如果结果不为零,则表示有一个,因此必须打印arr[j]

显然,该函数的问题在于它仅限于变量counter可以容纳的位数。这取决于其声明的类型和体系结构/编译器,但通常它将是 32 或 64。