Algorithm 生成给定二进制字符串的子集,这段代码是如何工作的?
我在寻找子集生成的答案时遇到Algorithm 生成给定二进制字符串的子集,这段代码是如何工作的?,algorithm,subset,Algorithm,Subset,我在寻找子集生成的答案时遇到 start N; //an integer X = N while true print X if( X == 0 ) break; X = (X-1) & N; end while end 有人能解释一下为什么这个代码有效吗?提前谢谢 谢谢你的回答。我的想法如下: 如果我们把N看作一个掩码,那么重要的位是N中1的位置。我们称之为掩蔽空间。 由于X始终是N的一个子集,因此X的倒计时就像在屏蔽空间中倒计时一样
start
N; //an integer
X = N
while true
print X
if( X == 0 )
break;
X = (X-1) & N;
end while
end
有人能解释一下为什么这个代码有效吗?提前谢谢
谢谢你的回答。我的想法如下: 如果我们把
N
看作一个掩码,那么重要的位是N
中1的位置。我们称之为掩蔽空间。
由于X
始终是N
的一个子集,因此X
的倒计时就像在屏蔽空间中倒计时一样(位在屏蔽空间中翻转)。
因此,在
X
和(X-1)&N
之间没有其他子集。您可以用以下参数证明它是有效的:
(X-1)
始终生成较小的数字(忽略环绕)(X-1)&N您可以用以下参数证明它有效:
(X-1)
始终生成较小的数字(忽略环绕)
(X-1)&N要理解发生了什么,你应该完全理解减法,它实际上是这里最复杂的运算
另一种思考减法1的方法是,从最低有效位开始看数字,然后朝最高有效位扫描,直到找到第一个1。翻转每一位直到并包括1
与&
组合使用时,它会抛出最低的设置位,然后再放入该位右侧以前为1的任何位
比如说,
10110 start here
10101 subtract 1
10100 and with N
10011 subtract 1
10010 and with N
10001 subtract 1
10000 and with N
01111 subtract 1
00110 and with N
要理解发生了什么,你应该完全理解减法,这实际上是这里最复杂的运算
另一种思考减法1的方法是,从最低有效位开始看数字,然后朝最高有效位扫描,直到找到第一个1。翻转每一位直到并包括1
与&
组合使用时,它会抛出最低的设置位,然后再放入该位右侧以前为1的任何位
比如说,
10110 start here
10101 subtract 1
10100 and with N
10011 subtract 1
10010 and with N
10001 subtract 1
10000 and with N
01111 subtract 1
00110 and with N
这并不完全表明X
在每次迭代中变小:如果X
在N
中最右边的1位右边有一个1位,那么X=(X-1)&N
将保持X&N
不变。所以我们需要证明这是不可能的。显然,它不能在第一次迭代时,当X==N
时,X
的每次更新都以一个和N
结束,所以这样的位永远不会出现。@j_random_hacker,但这是这个答案第3点的结果,对吗?@harold:第3点确实意味着从第2次开始的每次迭代都会产生一个不同的值X&N
,但作为一个证据,这篇文章是不完整的。如前所述,第1点实际上是不相关的,因为它只描述了一个中间结果。相反,我们需要的是“如果X&~N==0
,那么(X-1)&N
,假设继续成立(即((X-1)&N)&~N==0
)”,然后是一个声明,表明该假设(X&~N==0
)在第一次迭代中保持不变。这并不表明X
在每次迭代中变小:如果X
在N
中最右边的1位右边有一个1位,那么X=(X-1)&N
将保持X&N
不变。所以我们需要证明这是不可能的。显然,它不能在第一次迭代时,当X==N
时,X
的每次更新都以一个和N
结束,所以这样的位永远不会出现。@j_random_hacker,但这是这个答案第3点的结果,对吗?@harold:第3点确实意味着从第2次开始的每次迭代都会产生一个不同的值X&N
,但作为一个证据,这篇文章是不完整的。如前所述,第1点实际上是不相关的,因为它只描述了一个中间结果。相反,我们需要的是“如果X&~N==0
,那么(X-1)&N
,假设继续成立(即((X-1)&N)&~N==0
)”,然后是一条语句,表明该假设(X&~N==0
)在第一次迭代中成立。