有一个问题问:



我写了下面的解决方案,它工作正常。

int secondRightmostZeroBit(int n) {
  return (int)Math.pow(2,Integer.toBinaryString(n).length()-1-Integer.toBinaryString(n).lastIndexOf('0',Integer.toBinaryString(n).lastIndexOf('0')-1))  ;
}

但是,下面是我投票也获得了最佳投票的解决方案,因为它只有几个字符可以满足要求,但我无法理解。有人可以解释一下位操纵如何帮助实现它。
int secondRightmostZeroBit(int n) {
  return ~(n|(n+1)) & ((n|(n+1))+1) ;
}

最佳答案

考虑具有至少两个0位的某个数字。这是一个这样的数字示例,其中最右边的2个0位标记为(x ... x是我们不关心的位,它们可以是0或1,而1 ... 1是零或更大的序列最右边的0位的右边和左边的1位):

x...x01...101...1 - that's n

如果在该数字上加1,则会得到:
x...x01...110...0 - that's (n+1)

这意味着最右边的0位翻转为1

因此n|(n+1)将为您提供:
x...x01...111...1 - that's n|(n+1)

如果将1添加到n|(n+1),则会得到:
x...x100........0 - that's (n|(n+1))+1

这意味着第二个最右边的0位也会翻转为1

现在,~(n|(n+1))
y...y10.........0 - that's ~(n|(n+1))

其中每个y位是对应的x位的倒数

因此~(n|(n+1)) & ((n|(n+1))+1)
0...010.........0

其中唯一的1位在输入数字的第二个最右边的0位的位置。

关于java - 位操作如何工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43510764/

10-11 16:46