什么是反转数字位的最快方法?

时间:2015-05-19 11:46:16

标签: algorithm

给定一个整数,n。倒数这个数字的最快方法是什么?例如,如果n = 5(101),则输出应为2(010)。不会将前缀0视为反向。这个问题的独特之处在于,我们不会考虑前缀0

我的方法

Convert n to binary as a string. For example, if n = 5 then I'll have string, say str, as `101`.
Convert 1 to 0 and 0 to 1 in the string. (output: 010)
Convert resultant binary string to number. (output: 2)

更多输入/输出示例:

Input: 7, Output: 0
Input: 8, Output: 7
Input: 10, Output: 5
Input: 98, Output: 29

正如您所看到的,我的方法看起来很幼稚或效率很低。有没有更好的方法,通过使用一些位操作操作或任何其他方式更快地获得所需的输出?

注意: n也可能是否定的!对于负数,必须考虑2的补码以反映这些位。

我不是要求确切的代码。伪代码或方法会有所帮助。

5 个答案:

答案 0 :(得分:2)

这个问题是可互联的(带有按位XOR指令的开销),其问题是将n舍入到最小数量的形式2 ^ k-1。对于32位int n,您可以为后者调整其中一个标准位:

m = n;
m |= m >> 1;
m |= m >> 2;
m |= m >> 4;
m |= m >> 8;
m |= m >> 16;
return m ^ n;

答案 1 :(得分:1)

unsigned reversed = 0;
while (num := 0) {
  reversed = reversed << 1;
  reversed |= (num & 1);
  num = num >> 1;
}

将低阶位移出原始位置,或者在反转时将它们移位到连续的高位。

答案 2 :(得分:1)

flip(n)= 2 ^(ceiling(lg(n))) - 1 - n,其中lg是对数基数2.

如果您知道n的最大设置位,那么您可以通过获取最大设置位并将1向左移1来快速获得2 ^ ceiling(lg(n))。

答案 3 :(得分:0)

如果表现真的很重要,你可以制表。

从MSB到LSB逐字节处理整数。如果该字节为空,则跳过。否则,使用256个条目(带前缀)的预计算查找表,以及后续字节,XOR。

if (B[0]) { B[0]= LUT[B[0]]; B[1]^= 255; B[2]^= 255; B[3]^= 255; }
else if (B[1]) { B[1]= LUT[B[1]]; B[2]^= 255; B[3]^= 255; }
else if (B[2]) { B[2]= LUT[B[2]]; B[3]=^255; }
else B[3]= LUT[B[3]];

您还可以使用适当的掩码一次性对32位进行异或。

答案 4 :(得分:0)

~n没有给出预期结果的原因是您号码中的所有前导零。要在将它们反转为1之后屏蔽这些零,直接的方法是:

m = abs(n);
result = ~m & (int)(exp2(ceil(log2(m)))-1);

通过获取(正)输入的base-2对数,生成正确长度的掩码。 n为2的幂的边界情况是正确的,因为结果中的前导1始终为0,因此将其从掩码中排除无关紧要。

性能可能是公平的,但编码简洁。