zoukankan      html  css  js  c++  java
  • 【剑指Offer-位运算】面试题15:二进制中1的个数

    题目描述

    输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

    思路1

    可以先判断该整数对应的二进制最右一位是不是1,判断方法为将整数的二进制和1做与运算(&),如果整数二进制的最右一位是1,则与运算结果为1,否则为0。将整数二进制最右一位进行判断后右移一位(>>),直至整数为0。但这种方法只能判断非负整数二进制中1的个数,因为负数二进制的第一位为1,当进行右移操作时,左边会补上1,最终造成死循环。

    思路2

    在思路1中是右移整数二进制&1进行判断,但这种方法会造成死循环。为了避免死循环,我们保持输入整数的二进制不变,对1左移(<<)后和整数二进制与操作进行判断,这样每次都能判断整数二进制中的一位,在这个算法中,循环的次数等于整数1的二进制位数,例如32位的整数需要循环32次。代码如下:

    class Solution {
    public:
         int  NumberOf1(int n) {
             unsigned int flag=1;    //要使用unsigned int
             int cnt=0;
             while(flag){
                 if(flag&n)
                     cnt++;
                 flag = flag<<1;
             }
             return cnt;
         }
    };
    

    需要注意的是,1的类型要是unsigned int,不能是int。

    思路3

    思路2可以准确统计整数二进制中1的个数,但总要循环32次。在思路3中,整数二进制中包含多少个1,就循环多少次。首先有一个技巧:把一个整数减去1后,再和原来的整数做与运算,得到的结果就相当于把原来整数二进制最靠右一位的1转为0。例如,整数二进制可以分为两种情况,最靠右一位的1就是最右一位(如1011)和最靠右一位的1不是最后一位(如1010)。最靠右一位的1就是最右一位,假设为1101,则1011-1=1100,1011&1100=1010,1011最右一位变成了1;当最靠右一位的1不是最后一位,假设为1010,此时1010-1=1001,1010&1001=1000,最靠右一位的1(从左往右第3位)变成了1。这样,整数二进制中有多少位1,就可以进行多少次上面的操作(因为每次都把最靠右一位的1变成0,直到所有的1都变成0,那么整数值也为0,即为循环终止条件)。代码如下:

    class Solution {
    public:
         int  NumberOf1(int n) {
             int cnt=0;
             while(n){
                 n = (n-1)&n;
                 cnt++;
             }
             return cnt;
         }
    };
    

    总结

    把一个整数减去1后,再和原来的整数做与运算,得到的结果就相当于把原来整数二进制最靠右一位的1转为0。

  • 相关阅读:
    【开发技术】Eclipse设置软tab(用4个空格字符代替)及默认utf-8文件编码(unix)
    【开发技术】Xcode3与xcode4.2模板对比(Xcode4.2开发之一些变化)
    cobol
    头文件的相互包含会导致错误
    ndk eclipse集成
    为何要用到NDK?
    Android之NDK开发
    一个完整的NDK编译过程
    NDK中 .so文件的加载
    Android.mk 变量解释
  • 原文地址:https://www.cnblogs.com/flix/p/12437380.html
Copyright © 2011-2022 走看看