2.1 二进制数中 1 的个数

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

分析与解法

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

int Count1(unsigned int v)
{
int num = ; while(v)
{
if( == v % )
{
++num;
} v /= ;
} return num;
}

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

int Count2(unsigned int v)
{
unsigned int num = ; while(v)
{
num += v & 0x01;
v >>= ;
} return num;
}

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

int Count3(unsigned int v)
{
int num = ; while(v)
{
v &= (v-);
++num;
} return num;
}

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

解法4:

int Count4(unsigned int v)
{
int num = ; switch(v)
{
case 0x0:
num = ;
break;
case 0x1:
case 0x2:
case 0x4:
case 0x8:
case 0x10:
case 0x20:
case 0x40:
case 0x80:
num = ;
break;
case 0x3:
case 0x6:
case 0xc:
case 0x18:
case 0x30:
case 0x60:
case 0xc0:
num = ;
break;
//.....
} return num;
}

解法5:

unsigned int table[] =
{
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , ,
}; int CountTable(unsigned int v)
{
return table[v & 0xff] +
table[(v >> ) & 0xff] +
table[(v >> ) & 0xff] +
table[(v >> ) & 0xff];
}

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

int Count6(unsigned int v)
{
v = (v & 0x55555555) + ((v >> ) & 0x55555555);
v = (v & 0x33333333) + ((v >> ) & 0x33333333);
v = (v & 0x0f0f0f0f) + ((v >> ) & 0x0f0f0f0f);
v = (v & 0x00ff00ff) + ((v >> ) & 0x00ff00ff);
v = (v & 0x0000ffff) + ((v >> ) & 0x0000ffff); return v;
}

扩展问题:求整数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. css图片文字

    1.浏览器是把 html 和 css 一起下载并执行的,计算机里把两件事情同时做  异步加载.计算机中的同步异步和我们生活中的正好是相反的. 补充: 同步,是所有的操作都做完,才返回给用户结果.即写完 ...

  2. npm install 时 提示err code EINTEGRITY报错

    1.报错截图如图: 2.报错缘由:因npm 版本问题导致 3.解决方法:升级npm版本(npm i -g npm),再重新npm install即可.

  3. js-打印九九乘法表

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. hdu 3450 后缀数组

    题目大意: 求多个字符串的最长公共子串 基本思路: 参加我的博客hdu2774 代码如下: #include<cstdio> #include<cstring> using n ...

  5. java基础方法笔记

    Java环境 1.编译 javac HelloWorld.java 2.运行 java HelloWorld 3.执行class文件 java -classpath C:\java\myclasses ...

  6. thinkphp SAE

    SAE介绍 Sina App Engine(简称SAE)是新浪研发中心开发的国内首个公有云计算平台,是新浪云计算战略的核心组成部分,作为一个简单高效的分布式Web服务开发.运行平台越来越受开发者青睐. ...

  7. 【书上讲解】最大m段子段和问题

    描述 [题解] 设f[i][j]表示前i个数字分成了j段的最大子段和. 则f[i][j] = max(f[i-1][j]+a[i] (第i个数字和第j段合在一起),f[k][j-1]+a[i] (第i ...

  8. ac自动机暴力跳fail匹配——hdu5880

    很简单的题,ac自动机里再维护一个len表示每个状态的串长,用s去query时每到一个结点都要暴力跳fail,因为有可能这个结点不是,但是其fail是危险结点,找到一个就直接break 再用个差分数组 ...

  9. 3-基于LoG的特征检测子

  10. drag事件

    <!DOCTYPE HTML><html>  <head>      <title>拖动事件</title>    <style> ...