微软算法100题28 整数的二进制表示中1 的个数

任意给定一个32位无符号整数n,求n的二进制表示中1的个数,比如n = 5(0101)时,返回2,n = 15(1111)时,返回4

思路:

最直观的方法是对n和0001做&运算,如果结果为1,则counter加一,否则不变,然后将n右移一位,直到n=0为止. 方法count1和count2都是这种思路,其时间复杂度是n的二进制的位数

还有一种更快的方法是count3,思路是对整数n,不断清除其最右边的1,并累计计数器,直到n为0为止,这种算法的好处时其时间复杂度只和N中含有的1的个数有关

//8(1000) = 7(0111) + 1(0001) => 8(1000) & 7(0111) = 0(0000)
//7(0111) = 6(0110) + 1(0001) => 7(0111) & 6(0110) = 6(0110)

可以通过n&n-1来移除其最右边的1 为什么?因为对N的二进制来说,n的二进制等于n-1的二进制最低位加1, 如上述例子 1000=0111 + 0001 所以1000&0111=0000

0111=0110+0001,所以0111&0110=0110 (最低位被清除了)

 1 package com.rui.microsoft;
 2 
 3 public class Test28_CountBinaryOne {
 4 
 5     public static void main(String[] args) {
 6         System.out.println(count3(7));
 7     }
 8     
 9     public static int count1(int n){
10         if(n == 0) return 0;
11         int total = 0;
12         
13         while(n>0){
14             if((n & 1) == 1){
15                 total++;
16             }
17             n >>= 1;
18         }
19         
20         return total;
21     }
22     
23     public static int count2(int n){
24         if(n == 0) return 0;
25         int total = 0;
26         for(;n>0;n>>=1){
27             total += n&1;
28         }
29         return total;
30     }
31     
32     public static int count3(int n){
33         //可以通过不断清除最低位的1的方式来统计 n & n-1
34         //8(1000) = 7(0111) + 1(0001) => 8(1000) & 7(0111) = 0(0000)
35         //7(0111) = 6(0110) + 1(0001) => 7(0111) & 6(0110) = 6(0110)
36         if(n == 0) return 0;
37         int total = 0;
38         for(;n>0;total++){
39             n &= n-1;
40         }
41         return total;
42     }
43 }
原文地址:https://www.cnblogs.com/aalex/p/4911429.html