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。

  • 相关阅读:
    第四季-专题11-LED驱动程序设计
    第四季-专题12-按键驱动程序设计
    第四季-专题9-Linux驱动开发前奏
    第四季-专题10-字符设备驱动模型
    第四季-专题7-Linux内核链表
    第四季-专题8-LINUX系统调用
    第四季-专题6-Linux内核子系统
    第四季-专题5-内核模块开发
    第四季-专题3-嵌入式Linux内核制作
    jquery js获取移动设备浏览器高度
  • 原文地址:https://www.cnblogs.com/flix/p/12437380.html
Copyright © 2011-2022 走看看