14

How to find the length of the longest consecutive bit string(either 1 or 0)?

00000000 11110000 00000000 00000000 -> If it is 0 then length will be 20

11111111 11110000 11110111 11111111 -> If it is 1 then length will be 12

11
  • 2
    @bithacker , don't you mean that "if 0, then length will be 20" ? Also, does this have to the the longest consecutive string AT THE END of the list? This is quite ambiguous. What about 10101111111010101 ? Commented Jul 21, 2010 at 23:48
  • @aaron mcdaid you are correct. if 0 the length will be 20. The answer for your other question is 1. The consecutive string can be anywhere. Commented Jul 21, 2010 at 23:52
  • @bithacker: I've just realised my own example was a bit ambiguous. My current understanding is that 0101000111101010 will be either three or four depending on whether you're looking for zero or one. Commented Jul 21, 2010 at 23:55
  • @aaron mcdaid since the longest consecutive string is from 1 so the answer would be 4. Commented Jul 22, 2010 at 0:09
  • Are you working with strings i.e char arrays, or with ints of some length? Commented Jul 22, 2010 at 0:14

10 Answers 10

27

The following is based on the concept that if you AND a bit sequence with a shifted version of itself, you're effectively removing the trailing 1 from a row of consecutive 1's.

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

Repeating this N times will reduce any sequence with N consecutive 1's to 0x00.

So, to count the number of consecutive 1's:

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

To count the number of consecutive 0's, simply invert and the same routine.

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

Proof of concept: 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)); } 

Output:

0 has 0 consecutive 1's 0 has 32 consecutive 0's f00000 has 20 consecutive 0's fff0f7ff has 12 consecutive 1's 
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for this answer as it is useful here, hackerrank.com/challenges/30-binary-numbers
I'd recommend unsigned int, to avoid signed-integer overflow undefined behaviour when you shift a 1 bit into the sign bit. (ISO C does not define the behaviour there, but most C implementations do. e.g. GNU C does unless you use -fsanitize=shift or -fsanitize=undefined.) int->unsigned conversion is always well-defined, and for 2's complement machines preserves the bit-pattern, so the result will be identical.
catonmat.net/low-level-bit-hacks is a good intro to how bithacks like this work, especially ones using + or - for carry propagation.
6

One simple way would be to simply loop over the bits, and keep track of the number of bits in a row which have had the same value, and the maximum that this value has reached.

Here's a simple C function which does just this:

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; } 

7 Comments

I did the downvote. I have since undone the downvote. It's not that I doubt the accuracy of the solution, it's just that it seems unhelpful. I assume that anybody asking this question is easily able to implement a correct, but very slow, solution themselves. I suspected the questioner needs something fast. But now I'm not so sure. So, I'll think I'll hold my fire for now, and neither upvote nor downvote.
Fair enough. Since the question didn't ask for a fast solution, I just went with a simple and straightforward one. Correctness first :).
@AaronMcDaid if I could I would downvote your comment :) It is quite trivial to see that there is no faster algorithm than O(number of digits) (and I speak about algorithm now, not implementation)
it's not so obvious to me. bit tricks (.. and algorithms) are often times non intuitive.
@TMS can you tell me the subtle difference between algorithm and implementation?
|
3

You can form a look up table to do it quickly for you. The bigger the table, the faster the lookup. 2x256 entry tables can do 8 bits at a time with a little bit twiddling. Add a 1s version of the table and start adding entries. That's probably how I'd go about it.

Comments

2

To use the table idea, you need something like

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; } 

initializing the table is straight-forward, but depends on your bit- and byte-ordering (little endian or big endian).

Comments

0

Since you didn't wrote what is bit string (regular int, byte array or char string I've assumed that it's char array

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; } 

Comments

0

Posting from iPhone withbig fingers.

If ones, then invert.

Loop over the input using a leadz function. For each iteration, shift the input to the left. Continue until you reach the end of the input. Note that you need to compare the original input length with the cumulative leadz counts.

Also, as an optimization, you can early abort when the remaining input length is less than the largest leadz you have seen.

There are many fast leadz algorithms online.

Comments

0

I don't agree with the tables idea, because I was trying it and realized that even though "BA" in ASCII would contain 5 consecutive 0's for 'B' and 5 consecutive 0's for 'A', they will not add together for 10 consecutive 0's. As a matter of fact, there would be 5 consecutive 0's maximum. (This was in reference to a simple "counting bits in a table idea." Chris Dodd has since expounded on how a table could be used accurately.)

I would use an algorithm like this:

#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; } 

In this algorithm, I assume the bitstream is represented as 8-bit characters. For each character, I look at the very last bit with a bitwise AND. If it's the same as the last bit, then I up the consecutive bit count, otherwise, I reset the count because the bits are no longer consecutive. I then use a bitwise shift operation to move the next bit in the character over for observation. Hope this helps!

My answer is effectively a duplicate of David Underhill's answer. :)

6 Comments

He has a char array of bytes, probably each byte is either '0' or '1', allowing you to make your solution even shorter.
Oops.... forgot, of all things, to actually keep track of the biggest number of consecutive 0's, so I added in max_consecutive0s. This is the value you'd want to return, print, etc.
@earlNameless: But then what fun would it be without bitwise operations? :)
@froggythefrog, true, I'd give up some sanity for fun
@froggythefrog your logic fails for the below. { 0x01, 0xff, 0x00, 0xff } should return 9 { 0x00, 0x01, 0xff, 0xff } should return 17 are u assuming little endian or big endian?
|
0

If you're just looking for a byte string of four bytes, you can pack these into an unsigned long and use an algorithm like this:

int CountConsecutiveOnes(unsigned long n) { unsigned long m = n; int k = 0; while (m) { ++k; n >>= 1; m &= n; } return k; } 

For counting zeros, just taking the bitwise complement first.

If you need to count byte strings longer than four, you can just implement the operations x >>= 1 and x & y either directly on the byte strings or it may be more efficient to use strings of unsigned long so the carry checks on the implementation of x >>= 1 aren't too expensive.

Comments

0

It may help you.... First convert your binary number to String say bits. It will give you max number of consecutive 1's (in java)

String[] split = bits.split("0"); Arrays.sort(split); int maxLength = split[split.length - 1].length(); 

Comments

0
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); } 

You can this code here: https://github.com/VishalSKumar/DSFiddle/blob/master/src/main/java/com/vishalskumar/hackerrank/MaxConsecutiveOneInBinary.java

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.