2.1 二进制数中 1 的个数

实现一个函数,输入一个无符号整数,输出该数二进制中的1的个数。例如把9表示成二进制是1001,有2位是1,因此如果输入9,该函数输出2

分析与解法

解法1:利用十进制和二进制相互转化的规则,依次除余操作的结果是否为1,代码如下:

  1. int Count1(unsigned int v)
  2. {
  3. int num = ;
  4.  
  5. while(v)
  6. {
  7. if( == v % )
  8. {
  9. ++num;
  10. }
  11.  
  12. v /= ;
  13. }
  14.  
  15. return num;
  16. }

解法2:向右移位操作同样可以达到相同的目的,唯一不同的是,移位之后如何来判断是否有1存在。对于这个问题,举例:10100001,在向右移位的过程中,我们会把最后一位丢弃,因此需要判断最后一位是否为1,这个需要与00000001进行位“与”操作,看结果是否为1,如果为1,则表示当前最后八位最后一位为1,否则为0,解法代码实现如下,时间复杂度为O(log2v)。

  1. int Count2(unsigned int v)
  2. {
  3. unsigned int num = ;
  4.  
  5. while(v)
  6. {
  7. num += v & 0x01;
  8. v >>= ;
  9. }
  10.  
  11. return num;
  12. }

解法3:利用"与"操作,不断清除n的二进制表示中最右边的1,同时累加计数器,直至n为0,这种方法速度比较快,其运算次数与输入n的大小无关,只与n中1的个数有关。如果n的二进制表示中有M个1,那么这个方法只需要循环k次即可,所以其时间复杂度O(M),代码实现如下:

  1. int Count3(unsigned int v)
  2. {
  3. int num = ;
  4.  
  5. while(v)
  6. {
  7. v &= (v-);
  8. ++num;
  9. }
  10.  
  11. return num;
  12. }

编程之美同时给出了8bit的情况下,解法4:使用分支操作,解法5:查表法 再计算32bit无符号整数时,需要将32bit切为4部分 然后每部分分别运用解法4解法5下面仅给出代码:

解法4:

  1. int Count4(unsigned int v)
  2. {
  3. int num = ;
  4.  
  5. switch(v)
  6. {
  7. case 0x0:
  8. num = ;
  9. break;
  10. case 0x1:
  11. case 0x2:
  12. case 0x4:
  13. case 0x8:
  14. case 0x10:
  15. case 0x20:
  16. case 0x40:
  17. case 0x80:
  18. num = ;
  19. break;
  20. case 0x3:
  21. case 0x6:
  22. case 0xc:
  23. case 0x18:
  24. case 0x30:
  25. case 0x60:
  26. case 0xc0:
  27. num = ;
  28. break;
  29. //.....
  30. }
  31.  
  32. return num;
  33. }

解法5:

  1. unsigned int table[] =
  2. {
  3. , , , , , , , , , , , , , , , ,
  4. , , , , , , , , , , , , , , , ,
  5. , , , , , , , , , , , , , , , ,
  6. , , , , , , , , , , , , , , , ,
  7. , , , , , , , , , , , , , , , ,
  8. , , , , , , , , , , , , , , , ,
  9. , , , , , , , , , , , , , , , ,
  10. , , , , , , , , , , , , , , , ,
  11. , , , , , , , , , , , , , , , ,
  12. , , , , , , , , , , , , , , , ,
  13. , , , , , , , , , , , , , , , ,
  14. , , , , , , , , , , , , , , , ,
  15. , , , , , , , , , , , , , , , ,
  16. , , , , , , , , , , , , , , , ,
  17. , , , , , , , , , , , , , , , ,
  18. , , , , , , , , , , , , , , ,
  19. };
  20.  
  21. int CountTable(unsigned int v)
  22. {
  23. return table[v & 0xff] +
  24. table[(v >> ) & 0xff] +
  25. table[(v >> ) & 0xff] +
  26. table[(v >> ) & 0xff];
  27. }

平行算法,思路:将v写成二进制形式,然后相邻位相加,重复这个过程,直到只剩下一位。以217(11011001)为例,有图有真相,下面的图足以说明一切了。217的二进制表示中有5个1。

  1. int Count6(unsigned int v)
  2. {
  3. v = (v & 0x55555555) + ((v >> ) & 0x55555555);
  4. v = (v & 0x33333333) + ((v >> ) & 0x33333333);
  5. v = (v & 0x0f0f0f0f) + ((v >> ) & 0x0f0f0f0f);
  6. v = (v & 0x00ff00ff) + ((v >> ) & 0x00ff00ff);
  7. v = (v & 0x0000ffff) + ((v >> ) & 0x0000ffff);
  8.  
  9. return v;
  10. }

扩展问题:求整数A和B的二进制表示中有多少位不同。

    思路:首先A与B进行异或运算,结果M,计算M中含有的1的个数。

BCZM: Chapter 2的更多相关文章

  1. BCZM: Chapter 1

    1.1 CPU 占用率 https://www.cnblogs.com/TenosDoIt/p/3242910.html 1.2 中国象棋将帅 https://blog.csdn.net/kabini ...

  2. Modern C++ CHAPTER 2(读书笔记)

    CHAPTER 2 Recipe 2-1. Initializing Variables Recipe 2-2. Initializing Objects with Initializer Lists ...

  3. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- ApiWrapper

    前面两片文章讲解了通过AIDL和Messenger两种方式实现Android IPC.而本文所讲的并不是第三种IPC方式,而是对前面两种方式进行封装,这样我们就不用直接把Aidl文件,java文件拷贝 ...

  4. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger

    Messenger类实际是对Aidl方式的一层封装.本文只是对如何在Service中使用Messenger类实现与客户端的通信进行讲解,对Messenger的底层不做说明.阅读Android Prog ...

  5. [转]第四章 使用OpenCV探测来至运动的结构——Chapter 4:Exploring Structure from Motion Using OpenCV

    仅供参考,还未运行程序,理解部分有误,请参考英文原版. 绿色部分非文章内容,是个人理解. 转载请注明:http://blog.csdn.net/raby_gyl/article/details/174 ...

  6. 《深入理解计算机系统》 Chapter 7 读书笔记

    <深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...

  7. 《Linux内核设计与实现》Chapter 3 读书笔记

    <Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...

  8. PRML Chapter 2. Probability Distributions

    PRML Chapter 2. Probability Distributions P68 conjugate priors In Bayesian probability theory, if th ...

  9. PRML Chapter 1. Introduction

    PRML Chapter 1. Introduction 为了防止忘记,要把每章的重要内容都记下来,从第一章开始 2012@3@28 今天又回去稍微翻了一下第一章内容,发现第一次看的时候没有看透,每次 ...

随机推荐

  1. 2018-2-13-win10-uwp-hashcash

    title author date CreateTime categories win10 uwp hashcash lindexi 2018-2-13 17:23:3 +0800 2018-2-13 ...

  2. sum - 计算文件的校验和,以及文件占用的块数

    总览 (SYNOPSIS) ../src/sum [OPTION]... [FILE]... 描述 (DESCRIPTION) 显示 每个 文件 FILE 的 校验和, 以及 他们 占用的 块数. - ...

  3. 类定义包含vecot<类>对象

    #include "stdafx.h" #include <vector> using namespace std; class ControlPosition { p ...

  4. nodejs 静态资源文件与登陆交互

    server2.js var express=require('express'); var expressStatic=require('express-static'); var server=e ...

  5. Linux直接在通过终端打开图片文件

    为了提高效率,减少使用鼠标,有时候想直接通过终端的命令打开一个图片进行查看.可以使用的命令有: eog filename display filename 再使用Alt+F4就可以关闭窗口,尽量达到手 ...

  6. leetcode-164周赛-1266-访问所有点的最小时间

    题目描述: 自己的解: class Solution: def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int: re ...

  7. Work 4(通知类) (2019.04.25)

  8. J2EE学习篇之--Spring技术详解

    今天我们来看一下Spring的相关知识,我们知道Spring也是一个开源的框架,这个框架并不像是Struts一样,这个框架是可以用在Java的所有地方,所以,其实开发Android的时候我们也是可以使 ...

  9. 栈+括号序列+暴力枚举——cf1248D1

    这个复杂度首先就想到是n3的复杂度,n2枚举换的位置,求值在花费n复杂度 判断一个序列有多少独立的括号子串时用栈处理一下即可 /* 枚举交换两个括号的位置,然后再对新的序列判一次即可 */ #incl ...

  10. Html加水印和禁用复制和右键(jquery.watermark.js)

    近期遇到一个需求,需要在页面背景加上自己的水印和禁止用户在页面复制粘贴 解决: 水印使用的是jquery.watermark.js插件,这个插件可以在html背景上加水印,同时可以设置相关属性值. 相 ...