繁体   English   中英

查找1或0的连续位字符串

[英]Finding consecutive bit string of 1 or 0

如何找到最长的连续位串的长度(1或0)?

00000000 11110000 00000000 00000000->如果为0,则长度为20

11111111 11110000 11110111 11111111->如果为1,则长度为12

以下是基于这样的概念,如果你AND一个位序列转变的本身的版本,你有效地从连续的1的行删除尾部1。

      11101111   (x)
    & 11011110   (x << 1)
    ----------
      11001110   (x & (x << 1)) 
        ^    ^
        |    |
   trailing 1 removed

重复此N次将把N个连续的1的任何序列减少到0x00

因此,要计算连续的1的数量:

int count_consecutive_ones(int in) {
  int count = 0;
  while (in) {
    in = (in & (in << 1));
    count++;
  }
  return count;
}

要计算连续0的数量,只需将求反并使用相同的例程即可。

int count_consecutive_zeros(int in) {
  return count_consecutive_ones(~in);
} 

概念验证: http//ideone.com/Z1l0D

int main(void) {
  printf("%d has %d consecutive 1's\n", 0, count_consecutive_ones(0));
  printf("%d has %d consecutive 0's\n", 0, count_consecutive_zeros(0));

  /* 00000000 11110000 00000000 00000000 -> If it is 0 then length will be 20 */
  printf("%x has %d consecutive 0's\n", 0x00F00000, count_consecutive_zeros(0x00F00000));

  /* 11111111 11110000 11110111 11111111 -> If it is 1 then length will be 12 */
  printf("%x has %d consecutive 1's\n", 0xFFF0F7FF, count_consecutive_ones(0xFFF0F7FF));
}

输出:

0 has 0 consecutive 1's
0 has 32 consecutive 0's
f00000 has 20 consecutive 0's
fff0f7ff has 12 consecutive 1's

一种简单的方法是简单地循环遍历位,并跟踪行中具有相同值的位数,以及达到该值的最大值。

这是一个简单的C函数,它就是这样做的:

int num_conseq_matching_bits(int n) {
    int i, max, cur, b, prevb;
    prevb = n & 1; /* 0th bit */
    cur = 1;
    max = 1;
    for(i=1; i<32; i++) {
        b = (n >> i) & 1; /* get the i'th bit's value */
        if(b == prevb) {
            cur += 1;
            if(cur > max)
                max = cur;
        }
        else {
            cur = 1; /* count self */
            prevb = b;
        }
    }
    return max;
}

您可以组成一个查询表来快速为您完成此操作。 表越大,查找速度越快。 2x256条目表可以一点点打乱地一次完成8位。 添加表的1s版本并开始添加条目。 那可能就是我要解决的方法。

要使用餐桌创意,您需要

static struct {
    int lead;  /* leading 0 bits */
    int max;   /* maximum 0 bits */
    int trail; /* trailing 0 bits */
} table[256] = { ....data.... };

int mostConsecutiveBits(unsigned char *str, int length, bool count_ones) {
    int max = 0; /* max seen so far */
    int trail = 0; /* trailing 0s from previous bytes */
    while (length-- > 0) {
        int byte = *str++;
        if (count_ones)
            byte ^= 0xff;
        if (table[byte].max > max)
            max = table[byte].max;
        if (trail + table[byte].lead > max)
            max = trail + table[byte].lead;
        if (byte)
            trail = table[byte].trail;
        else
            trail += 8;
    }
    return max;
}

初始化表很简单,但是取决于位和字节的顺序(小字节序或大字节序)。

我不同意表格的想法,因为我尝试过这种做法,并且意识到即使ASCII中的“ BA”将对“ B”包含5个连续的0,对于“ A”包含5个连续的0,它们也不会相加10连续的0。 实际上,将有5个连续的0的最大值。 (这是参考简单的“计数表中的位数”。此后,克里斯·多德(Chris Dodd)阐述了如何正确使用表。)

我会使用这样的算法:

#include <iostream>
#include <algorithm>

using namespace std;

// Assumes Little Endian architecture
int mostConsecutiveBits(char str[], int length) {
    int currentConsecutiveBits=0; 
    int maxConsecutiveBits=0; 
    char currentBit;
    char lastBit=0; 
    char currentChar=str[0];
    int charCtr,bitCtr; 

    for (charCtr=length-1; charCtr>=0; charCtr--) {

        currentChar=str[charCtr];

        for (bitCtr=0; bitCtr<8; bitCtr++) {
            currentBit=currentChar & 1;

            if (currentBit!=lastBit) {
                maxConsecutiveBits=max(maxConsecutiveBits,currentConsecutiveBits);
                currentConsecutiveBits=1; 
                lastBit=currentBit;
            }
            else {
                currentConsecutiveBits++;
            }

            currentChar=currentChar>>1; 

        }
        maxConsecutiveBits=max(maxConsecutiveBits,currentConsecutiveBits);
    }

    return maxConsecutiveBits; 
}   


int main (int argc, char * const argv[]) {
    cout << mostConsecutiveBits("AB",2);
    return 0;
}

在此算法中,我假设位流表示为8位字符。 对于每个字符,我都将按位与看最后一位。 如果与最后一位相同,则我增加连续的位计数,否则,我重置计数,因为位不再连续。 然后,我使用按位移位操作将字符中的下一位移到上方进行观察。 希望这可以帮助!

我的回答实际上是David Underhill的回答的重复。 :)

由于您没有编写什么是位字符串(常规int,字节数组或char字符串,我假设它是char数组

int maxConsBits(char *pStr,char cChar)
{
    char curChar;
    int curMax = 0;
    int max = 0;
    while (pStr)
    {
       if (*pStr == cChar)
       {
          curMax++;
          if (curMax > max)
          {
             max = curMax;
          }
       }
       else
       {        
           curMax = 0;
       }
       pStr++;
   }
   return max;
}

用大手指从iPhone发布信息。

如果是,则反转。

使用Leadz函数循环输入。 对于每次迭代,将输入向左移动。 继续直到输入结束。 请注意,您需要将原始输入长度与累积的Leadz计数进行比较。

此外,作为优化,您可以在剩余输入长度小于您看到的最大Leadz时提前中止。

在线上有许多快速的Leadz算法。

如果您只是在寻找四个字节的字节串,则可以将它们打包成unsigned long并使用如下算法:

int CountConsecutiveOnes(unsigned long n)
{
    unsigned long m = n;
    int k = 0;

    while (m)
    {
        ++k;
        n >>= 1;
        m &= n;
    }

    return k;
}

要计算零,只需先按位补码即可。

如果您需要计数大于四个的字节字符串,则可以直接在字节字符串上执行x >>= 1x & y或者使用unsigned long字符串可能会更有效,因此对x >>= 1的实现并不太昂贵。

这可能对您有帮助。...首先将您的二进制数转换为字符串说位。 它将为您提供连续的最大1(在Java中)

String[] split = bits.split("0");
Arrays.sort(split);
int maxLength = split[split.length - 1].length();
public static int maxConsecutiveOneInBinaryNumber(int number) {
int count = 0;
int max = 0;
while (number != 0) {
  if ((number & 1) == 1) {
    count++;
  } else {
    max = Math.max(count, max);
    count = 0;
  }
  number = number >> 1;
}
return Math.max(count, max);
}

您可以在此处使用以下代码: https : //github.com/VishalSKumar/DSFiddle/blob/master/src/main/java/com/vishalskumar/hackerrank/MaxConsecutiveOneInBinary.java

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM