108

Efficient way to count number of 1s in the binary representation of a number in O(1) if you have enough memory to play with. This is an interview question I found on an online forum, but it had no answer. Can somebody suggest something, I cant think of a way to do it in O(1) time?

TimeToCodeTheRoad
  • 7,032
  • 16
  • 57
  • 70
  • 2
    So the question wants you to cheat - "enough" memory could easily be more bits than there are atoms in the observable universe. – harold Jan 15 '12 at 16:39
  • Wouldn't it be just an array of MAX_INT length? – Boris Treukhov Jan 15 '12 at 17:33
  • 1
    please correct me - if we have an array [0..MAX_INT-1] where the index is the actual number on input, and the data is the number of 1's for that number( and let's say it's implemented via content-addressable memory http://en.wikipedia.org/wiki/Content-addressable_memory) would not it be O(1)? – Boris Treukhov Jan 15 '12 at 18:11
  • 2
    That's probably the model interview solution, although I don't think it would satisfy a *purist* because it's limited by the data width of the addressable memory on the machine (say 64bit). It wouldn't work for numbers > 2^64 and as stated the question does not impose this restriction. If the question were revised to say "a 64 bit number" then yes, that's a good solution. – Tim Gee Jan 15 '12 at 18:31
  • 1
    On the other hand, for 64-bit numbers, the old bit counting methods are also O(1) and use almost no memory. – Daniel Fischer Jan 15 '12 at 18:34

22 Answers22

77

That's the Hamming weight problem, a.k.a. population count. The link mentions efficient implementations. Quoting:

With unlimited memory, we could simply create a large lookup table of the Hamming weight of every 64 bit integer

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • 11
    +1 for the proper naming of this problem. Although I think a complete answer would state that even using a lookup table wouldn't be O(1) time as the time to lookup any entry is dependent on the entry's size. – Tim Gee Jan 15 '12 at 17:42
  • @TimGee A LUT access is always considered as being O(1). When you have unlimited memory, you also have an unlimited address bus. So no matter which address (= input) you access, it's always just one memory access ;-) – Scolytus Oct 21 '14 at 20:45
  • @Scolytus, any references for "When you have unlimited memory, you also have an unlimited address bus."? – sasha.sochka Sep 11 '15 at 23:38
  • 1
    @sasha.sochka *unlimited memory* is a theoretical construct. It has no address bus at all, it's just the assumption that you always have enough memory and can always access it the same way, independent of its size. So in a real world implementation of *unlimited memory* your address bus will always be > log2(count(addressable_memory_units)). – Scolytus Sep 15 '15 at 06:55
  • There is an O(1) algorithm for counting bits, it's easily found and is very likely to be faster than any solution involving lookup tables. – Jack Aidley Dec 08 '15 at 10:55
  • 1
    @JackAidley where's the link? – Óscar López Dec 08 '15 at 14:18
70

I've got a solution that counts the bits in O(Number of 1's) time:

bitcount(n):
    count = 0
    while n > 0:
        count = count + 1
        n = n & (n-1)
    return count

In worst case (when the number is 2^n - 1, all 1's in binary) it will check every bit.

Edit: Just found a very nice constant-time, constant memory algorithm for bitcount. Here it is, written in C:

    int BitCount(unsigned int u)
    {
         unsigned int uCount;

         uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
         return ((uCount + (uCount >> 3)) & 030707070707) % 63;
    }

You can find proof of its correctness here.

AsukaMinato
  • 1,017
  • 12
  • 21
Sufian Latif
  • 13,086
  • 3
  • 33
  • 70
  • The idea of the question is to use flat time, i.e. no difference in running time whether there are zero, one or many 1's. – Vladislav Zorov Jan 15 '12 at 16:54
  • 1
    The second one is only constant time because the size of the input is constant, and in that case so is the first one. The first algorithm, is actually O(log n) in the general case due to bitwise AND and subtraction taking that long. – harold Jan 15 '12 at 20:03
  • 6
    Your first answer is O(log n) not O(1). Your second answer is O(1) but assumes a domain of 32 bits (input parameter is `unsigned int`). – Stephen Quan Feb 11 '12 at 21:19
  • Actually, we should specify what n is. For problem 1: If n is the number of bits in the original number, then this is O(n * number of 1s), which is O(n^2). If n is the value of the number, then this O(lg^2 n). – John Kurlak Jan 20 '13 at 23:16
  • 1
    Or does anyone know another page with the proof? – mostruash Jul 05 '14 at 18:14
  • @ParagS.Chandakkar I've put in a corrected link. The original link appears to be just a copy of this MSDN blog post. – Mark Ransom Jul 25 '14 at 21:17
  • 5
    If any of you wondering what n = n & (n-1) does, it clears the least significant set bit (1) of n. So effectively when n=0, we have looped 'answer' times inside the while. – Ε Г И І И О Dec 04 '19 at 09:47
  • @ΕГИІИО your explanation is awesome. Thanks! – nurgasemetey Feb 26 '21 at 18:06
27

Please note the fact that: n&(n-1) always eliminates the least significant 1.

Hence we can write the code for calculating the number of 1's as follows:

count=0;
while(n!=0){
  n = n&(n-1);
  count++;
}
cout<<"Number of 1's in n is: "<<count;

The complexity of the program would be: number of 1's in n (which is constantly < 32).

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Sriram Mahavadi
  • 417
  • 4
  • 8
19

I saw the following solution from another website:

    int count_one(int x){
        x = (x & (0x55555555)) + ((x >> 1) & (0x55555555));
        x = (x & (0x33333333)) + ((x >> 2) & (0x33333333));
        x = (x & (0x0f0f0f0f)) + ((x >> 4) & (0x0f0f0f0f));
        x = (x & (0x00ff00ff)) + ((x >> 8) & (0x00ff00ff));
        x = (x & (0x0000ffff)) + ((x >> 16) & (0x0000ffff));
        return x;
    }
AsukaMinato
  • 1,017
  • 12
  • 21
user2555279
  • 311
  • 2
  • 7
11
public static void main(String[] args) {

    int a = 3;
    int orig = a;
    int count = 0;
    while(a>0)
    {
        a = a >> 1 << 1;
        if(orig-a==1)
            count++;
        orig = a >> 1;
        a = orig;
    }
    
    System.out.println("Number of 1s are: "+count);
}
Marat
  • 15,215
  • 2
  • 39
  • 48
akus
  • 119
  • 1
  • 2
  • 4
    +1 Good answer. Try to add some explanation. Especially for the bit shifting parts in both directions, which may be confusing for some. – brimborium Oct 31 '12 at 13:41
  • 2
    Explanation: A) If least significant bit is 1, increase counter by 1 (here's how this part works: shifting right, then undoing shift sets least significant bit to 0... if difference between old number and new number is 1, then a 1 was removed) B) Divide number by 2 and take floor by shifting right 1 C) Repeat until number is 0. It would be easier to just AND the number with 1 to determine if the least significant digit is a 1. – John Kurlak Jan 20 '13 at 23:13
  • 3
    Hi, I was just curious, wouldn't a `if (orig & 1)` `count++;` `orig >>= 1;` be a little more efficient? – Chang Hyun Park Feb 03 '13 at 14:28
  • 2
    Or even better: `count += orig & 1;` `orig >>= 1;` – Noah May 25 '16 at 21:54
10
       countBits(x){
         y=0;
         while(x){   
           y += x &  1 ;
           x  = x >> 1 ;
         }
       }

thats it?

AsukaMinato
  • 1,017
  • 12
  • 21
user40521
  • 1,997
  • 20
  • 8
6

Below are two simple examples (in C++) among many by which you can do this.

  1. We can simply count set bits (1's) using __builtin_popcount().
int numOfOnes(int x) {
  return __builtin_popcount(x);
}
  1. Loop through all bits in an integer, check if a bit is set and if it is then increment the count variable.
int hammingDistance(int x) {
  int count = 0;
  for(int i = 0; i < 32; i++)
    if(x & (1 << i))
      count++;
  return count;
}
जलजनक
  • 3,072
  • 2
  • 24
  • 30
Gaurav Sharma
  • 1,584
  • 1
  • 11
  • 10
4

That will be the shortest answer in my SO life: lookup table.

Apparently, I need to explain a bit: "if you have enough memory to play with" means, we've got all the memory we need (nevermind technical possibility). Now, you don't need to store lookup table for more than a byte or two. While it'll technically be Ω(log(n)) rather than O(1), just reading a number you need is Ω(log(n)), so if that's a problem, then the answer is, impossible—which is even shorter.

Which of two answers they expect from you on an interview, no one knows.

There's yet another trick: while engineers can take a number and talk about Ω(log(n)), where n is the number, computer scientists will say that actually we're to measure running time as a function of a length of an input, so what engineers call Ω(log(n)) is actually Ω(k), where k is the number of bytes. Still, as I said before, just reading a number is Ω(k), so there's no way we can do better than that.

alf
  • 8,377
  • 24
  • 45
  • And what happens when we are dealing with 64-bit numbers? – leppie Jan 15 '12 at 16:21
  • 1
    *"if you have enough memory to play with"* for starters. Now, you don't need to store lookup table for more than a byte or two (yes I know it'll technically be O(log(n)) rather than O(1), but then just to read a number you need O(log(n))). – alf Jan 15 '12 at 16:24
  • I would think you can read a number in O(1) with hardware parallelism, but you're still stuck with O(log(k)) when you need to make a decision on that number (be it a lookup table or partial sum operation). – Tim Gee Jan 15 '12 at 17:46
2

Below will work as well.

nofone(int x) {
  a=0;
  while(x!=0) {
    x>>=1;
    if(x & 1)
      a++;
  }
  return a;
} 
MattCochrane
  • 2,900
  • 2
  • 25
  • 35
2

The following is a C solution using bit operators:

    int numberOfOneBitsInInteger(int input) {
      int numOneBits = 0;

      int currNum = input;
      while (currNum != 0) {
        if ((currNum & 1) == 1) {
          numOneBits++;
        }
        currNum = currNum >> 1;
      }
      return numOneBits;
    }

The following is a Java solution using powers of 2:

    public static int numOnesInBinary(int n) {
    
      if (n < 0) return -1;
    
      int j = 0;
      while ( n > Math.pow(2, j)) j++;
    
      int result = 0;
      for (int i=j; i >=0; i--){
        if (n >= Math.pow(2, i)) {
            n = (int) (n - Math.pow(2,i));
            result++;    
        }
      }
    
      return result;
    }
AsukaMinato
  • 1,017
  • 12
  • 21
eb80
  • 4,700
  • 5
  • 25
  • 30
1

The function takes an int and returns the number of Ones in binary representation

public static int findOnes(int number)
{

    if(number < 2)
    {
        if(number == 1)
        {
            count ++;
        }
        else
        {
            return 0;
        }
    }

    value = number % 2;
        
    if(number != 1 && value == 1)
        count ++;

    number /= 2;
        
    findOnes(number);
        
    return count;
}
zforgo
  • 2,508
  • 2
  • 14
  • 22
Roshan
  • 521
  • 4
  • 16
1

I came here having a great belief that I know beautiful solution for this problem. Code in C:

        short numberOfOnes(unsigned int d) {
            short count = 0;

            for (; (d != 0); d &= (d - 1))
                ++count;

            return count;
        }

But after I've taken a little research on this topic (read other answers:)) I found 5 more efficient algorithms. Love SO!

There is even a CPU instruction designed specifically for this task: popcnt. (mentioned in this answer)

Description and benchmarking of many algorithms you can find here.

AsukaMinato
  • 1,017
  • 12
  • 21
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
1

By utilizing string operations of JS one can do as follows;

    0b1111011.toString(2).split(/0|(?=.)/).length // returns 6

or

    0b1111011.toString(2).replace("0","").length  // returns 6
AsukaMinato
  • 1,017
  • 12
  • 21
Redu
  • 25,060
  • 6
  • 56
  • 76
0

In python or any other convert to bin string then split it with '0' to get rid of 0's then combine and get the length.

len(''.join(str(bin(122011)).split('0')))-1
António Almeida
  • 9,620
  • 8
  • 59
  • 66
ben
  • 1
0

The below method can count the number of 1s in negative numbers as well.

private static int countBits(int number)    {
    int result = 0;
    while(number != 0)  {
        result += number & 1;
        number = number >>> 1;
    }
    return result;
}

However, a number like -1 is represented in binary as 11111111111111111111111111111111 and so will require a lot of shifting. If you don't want to do so many shifts for small negative numbers, another way could be as follows:

private static int countBits(int number)    {
    boolean negFlag = false;
    if(number < 0)  { 
        negFlag = true;
        number = ~number;
    }

    int result = 0;
    while(number != 0)  {
        result += number & 1;
        number = number >> 1;
    }
    return negFlag? (32-result): result;
}
Menezes Sousa
  • 1,448
  • 2
  • 18
  • 18
0

I had to golf this in ruby and ended up with

    l=->x{x.to_s(2).count ?1}

Usage :

l[2**32-1] # returns 32

Obviously not efficient but does the trick :)

AsukaMinato
  • 1,017
  • 12
  • 21
hoang
  • 1,887
  • 1
  • 24
  • 34
0

Ruby implementation

    def find_consecutive_1(n)
      num = n.to_s(2)
      arr = num.split("")
      counter = 0
      max = 0
      arr.each do |x|
          if x.to_i==1
              counter +=1
          else
              max = counter if counter > max
              counter = 0 
          end
          max = counter if counter > max  
      end
      max
    end

    puts find_consecutive_1(439)
AsukaMinato
  • 1,017
  • 12
  • 21
Jagdish
  • 752
  • 8
  • 23
0

Two ways::

/* Method-1 */
int count1s(long num)
{
    int tempCount = 0;

    while(num)
    {
        tempCount += (num & 1); //inc, based on right most bit checked
        num = num >> 1;         //right shift bit by 1
    }

    return tempCount;
}

/* Method-2 */
int count1s_(int num)
{
    int tempCount = 0;

    std::string strNum = std::bitset< 16 >( num ).to_string(); // string conversion
    cout << "strNum=" << strNum << endl;
    for(int i=0; i<strNum.size(); i++)
    {
        if('1' == strNum[i])
        {
            tempCount++;
        }
    }

    return tempCount;
}

/* Method-3 (algorithmically - boost string split could be used) */
1) split the binary string over '1'.
2) count = vector (containing splits) size - 1

Usage::

    int count = 0;

    count = count1s(0b00110011);
    cout << "count(0b00110011) = " << count << endl; //4

    count = count1s(0b01110110);
    cout << "count(0b01110110) = " << count << endl;  //5

    count = count1s(0b00000000);
    cout << "count(0b00000000) = " << count << endl;  //0

    count = count1s(0b11111111);
    cout << "count(0b11111111) = " << count << endl;  //8

    count = count1s_(0b1100);
    cout << "count(0b1100) = " << count << endl;  //2

    count = count1s_(0b11111111);
    cout << "count(0b11111111) = " << count << endl;  //8

    count = count1s_(0b0);
    cout << "count(0b0) = " << count << endl;  //0

    count = count1s_(0b1);
    cout << "count(0b1) = " << count << endl;  //1
parasrish
  • 3,864
  • 26
  • 32
0

The best way in javascript to do so is

    function getBinaryValue(num){
     return num.toString(2);
    }

    function checkOnces(binaryValue){
        return binaryValue.toString().replace(/0/g, "").length;
    }

where binaryValue is the binary String eg: 1100

AsukaMinato
  • 1,017
  • 12
  • 21
0

A Python one-liner

def countOnes(num):
    return bin(num).count('1')
stuckoverflow
  • 625
  • 2
  • 7
  • 23
0

There's only one way I can think of to accomplish this task in O(1)... that is to 'cheat' and use a physical device (with linear or even parallel programming I think the limit is O(log(k)) where k represents the number of bytes of the number).

However you could very easily imagine a physical device that connects each bit an to output line with a 0/1 voltage. Then you could just electronically read of the total voltage on a 'summation' line in O(1). It would be quite easy to make this basic idea more elegant with some basic circuit elements to produce the output in whatever form you want (e.g. a binary encoded output), but the essential idea is the same and the electronic circuit would produce the correct output state in fixed time.

I imagine there are also possible quantum computing possibilities, but if we're allowed to do that, I would think a simple electronic circuit is the easier solution.

Tim Gee
  • 1,062
  • 7
  • 9
0

I have actually done this using a bit of sleight of hand: a single lookup table with 16 entries will suffice and all you have to do is break the binary rep into nibbles (4-bit tuples). The complexity is in fact O(1) and I wrote a C++ template which was specialized on the size of the integer you wanted (in # bits)… makes it a constant expression instead of indetermined.

fwiw you can use the fact that (i & -i) will return you the LS one-bit and simply loop, stripping off the lsbit each time, until the integer is zero — but that’s an old parity trick.

kai26873
  • 11
  • 1