[LeetCode#191]Number of Bits

Problem:

Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also known as the Hamming weight).

For example, the 32-bit integer ’11' has binary representation 00000000000000000000000000001011, so the function should return 3.

Analysis:

This problem is like a magic, it could teach you a mgic skill in bit operation.

The instant idea:
Let us count the bit one by one, the easy way is to use a dividend (initial value is 2^31).
Theoretically, all integer could be represented in the form : 
 digit(31)*2^31 + digit(30)*2^30 + digit(29)*2^29 + ...
It could be solved by following pattern.
Assume: dividen = 2^i
digit = n / dividen  (n is no larger than 2^(i+1))
The digit is the digit at 'i' index.
For next index, we need update dividen
dividen = dividen / 2;

However that's just theoretical way!!!-.-

Wrong solution:

public int hammingWeight(int n) {
        int count  = 0;
        long dividen = 1;
        int digit = 0;
        for (int i = 0; i < 31; i++)
            dividen = dividen * 2; 
        while (n != 0) {
            digit = n / dividen;
            if (digit == 1)
                count++;
            n = n % dividen;
            dividen = dividen / 2;
        }
        return count;
}
Wrong case:
Input:
1 (00000000000000000000000000000001)
Output:
0
Expected:
1

Reason:
For ordinary integer, it has reserved one bit for indicate 'negative' or 'positive' of a number. Only 31 bit could be used for representing digits.
Positive Range: [0, 2^31-1]
Negative Range: [-1, -(2^31)]
Why negtaive could reach 2^31, cause for "0000...000", it is no need for representing '-0', thus we use it for representing '-(2^31)'.

Reference:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Thus the following code could exceed range of positive number. 
----------------------------------------------------------------------
for (int i = 0; i < 31; i++)
    dividen = dividen * 2; 
----------------------------------------------------------------------


A magic way to solve this problem:
Skill:
How to wipe out the last '1' of a integer?
n = n & (n-1)
Reason:
n-1 would turn the last '1' into '0', and all '0' after it into '1'.
Then we use '&', to keep recovering all bits except the last '1'. (has already been changed into '0')
Case:
n =     11110001000
&
n - 1 = 11110000000
ans =   11110000000
        
Great! Right!

Don't mix this skill with 
n = n ^ (n-1)
Which could keep the rightmost '1' bit only, all other bit were set into '0'.
Reference:
http://www.cnblogs.com/airwindow/p/4765145.html

Solution:

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int count  = 0;
        while (n != 0) {
            count++;
            n = n & (n-1);
        }
        return count;
    }
}

 

posted @ 2015-08-31 12:31  airforce  阅读(167)  评论(0编辑  收藏  举报