给定二进制数,如何在O(1)时间内从右边找到第n个设置位?

时间:2015-11-02 15:50:28

标签: algorithm bit-manipulation

让我们说x = 1110(12月14日)我想找到右边的第二个设置位0100(12月4个)

又一个例子,假设x = 10110010(十二月份为178),我想要右边的第三个设定位,即00100000(十二月三十二日)

如何找到它?有黑客吗?

3 个答案:

答案 0 :(得分:3)

从数字中减去一个将清除设置的最低有效位,同时设置低于该值的位。与原始数字进行AND运算将留下一个等于原始数字的数字,除非原始最低设置位清零。该过程可以迭代N次以产生具有最低N个设置位的数字。由第N次迭代(如果有的话)改变的位将是原始中设置的第N个最低位。

答案 1 :(得分:1)

假设一个名为 number 的二进制补码有符号32位整数是输入(因此只计算for循环中的位0到30):

int number = (1 << 3) | 1; // this is the input, it can be whatever you like
int currentLsbCount = 0;
int desiredLsbCount = 2; // this is your n
int foundLsb = 0;
int foundLsbIndex = 0;

for (int i = 0; i < 31; i++)
{
    int bit = (number >> i) & 1;

    if (bit == 1)
    {
        ++currentLsbCount;
    }

    if (currentLsbCount == desiredLsbCount)
    {
        foundLsb = number & (1 << i);

        foundLsbIndex = i;

        break;
    }
}

foundLsb 将保持该值,如果输入为零,则为零; foundLsbIndex 将保存该位的索引。

据我所知,你必须迭代。没有比循环比特更快的方法。您可以添加一些跳过逻辑,但它不会改善最坏情况的时序。例如:

if ((number & ((1 << x) - 1)) == number)
{
    // the bottom x bits are zero...
}

这会增加最坏情况下的操作次数。

答案 2 :(得分:1)

在VB.NET中,我可能会执行以下操作:

Private Function ReturnBit(input As Long, num As Long) As Long
    Dim iResult As Long = 0    'Counts set bits.
    Dim work As Long = input   'Working copy of input.

    'Looping from the LSB to the MSB of a byte. Adjust for desired 
    'length, 15 for 2 bytes, 31 for 4 bytes, etc.
    For i As Integer = 0 To 7
        'If the working variable is 0, the input does not contain as
        'many set bits as required. Return -1 if you wish.
        If work = 0 Then Return 0

        'Add the now LSB if 1, 0 otherwise. 
        iResult += (work And 1)

        'iResult contains the number of set bits now. If this is
        'the requested number, return this number. If you're just after
        'the position, just return i instead. Instead of 2^i it could be
        'more efficient to use 1<<i, but I'd rely on the compiler for
        'this.
        If iResult = num Then Return CLng(2 ^ i)

        'Remove the LSB from the working copy.
        work >>= 1
    Next
    Return 0    'Not enough set bits in input.
End Function