https://leetcode.com/problems/number-of-1-bits/
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.
解题思路:
求出二进制表示中1的数量,这题看似简单,却不容易。
首先用最朴素的二进制数学计算的方法,想算出n中的1的多少。但是却错了。
public class Solution { // you need to treat n as an unsigned value public int hammingWeight(int n) { int count = 0; while(n > 0){ if(n % 2 == 1){ count++; } n = n / 2; } return count; } }
问题就是,java中是没有unsigned int的,java中int是32位的,但是大小却是-2^16~2^16-1,于是最大值只有2147483647。
下面是两个网友的解法,依然是采用位运算。方法不同,道理却是一致。
1. n每次和1按位取与,结果只有两种可能,1或0。如果是1,就代表末尾为1,count++。
但是要注意的是,n的右移一位必须使用无符号的>>>。
public class Solution { // you need to treat n as an unsigned value public int hammingWeight(int n) { int count = 0, mask = 1; while(n != 0){ // if((n & 1) == 1 {也可以 if((n & 1) == 1){ count++; } n = n >>> 1; } return count; } }
第二种方法,n不动,但是使用一个mask。mask每次左移一位,和n去按位与,如果结果不为0,就代表这一位一定是1。
注意,这里的条件一定是(n&mask)!=0,而不能是(n&mask) == 1,因为这是mask的1不在最后一位了。
但是,这个方法的循环是一定要执行32次的,而上面的方法不必。
public class Solution { // you need to treat n as an unsigned value public int hammingWeight(int n) { int count = 0, mask = 1; for(int i = 0; i < 33; i++){ if((n & mask) != 0){ count++; } mask = mask << 1; } return count; } }
总结一下,使用按位运算是计算机计算的实际过程。左移相当于*2,右移是/2。&1就是/2的余数。
另外,加法也可以通过位运算来实现。a+b的结果,可以看成是,无进位的位运算+单纯进位的位运算的和。
那么,每一位的位运算,无进位的就相当于a^b,单纯的进位是(a&b)<<1。将他们相加即可。
特别注意,这其实是一个递归的运算,我们另它为add(a, b),递归调用它,直到b==0即可。
http://guozi149.me/series/coding-interview/831
https://leetcode.com/discuss/30605/simple-java-solution-bit-shifting
https://leetcode.com/discuss/31671/value-2147483647-test-include-value-2147483648-system-wrong