1.问题描述

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

2.分析与解法

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

int Count1(unsigned int v)
{
int num = 0;

while(v)
{
if(v % 2 == 1)
{
num++;
}
v = v/2;
}

return num;
}

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

int Count2(unsigned int v)
{
unsigned int num = 0;

while(v)
{
num += v & 0x01;
v >>= 1;
}
return num;
}

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

int Count3(unsigned int v)
{
int num = 0;

while(v)
{
v &= (v-1);
num++;
}
return num;
}

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

解法4:
int Count4(unsigned int v)
{
int num = 0;

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

解法5:
unsigned int table[256] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};

int CountTable(unsigned int v)
{
return table[v & 0xff] +
table[(v >> 8) & 0xff] +
table[(v >> 16) & 0xff] +
table[(v >> 24) & 0xff] ;
}

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

代码如下:

int Count6(unsigned int v)
{
v = (v & 0x55555555) + ((v >> 1) & 0x55555555) ;
v = (v & 0x33333333) + ((v >> 2) & 0x33333333) ;
v = (v & 0x0f0f0f0f) + ((v >> 4) & 0x0f0f0f0f) ;
v = (v & 0x00ff00ff) + ((v >> 8) & 0x00ff00ff) ;
v = (v & 0x0000ffff) + ((v >> 16) & 0x0000ffff) ;

return v ;
}

求整数A和B的二进制表示中有多少位不同
首先A与B进行异或运算,结果M,计算M中含有的1的个数。

BCZM : 2.1的更多相关文章

  1. BCZM: Chapter 2

    2.1 二进制数中 1 的个数 实现一个函数,输入一个无符号整数,输出该数二进制中的1的个数.例如把9表示成二进制是1001,有2位是1,因此如果输入9,该函数输出2 分析与解法 解法1:利用十进制和 ...

  2. BCZM: Chapter 1

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

  3. BCZM : 1.16

    24点游戏 解法一:穷举法 解法二:分治法

  4. BCZM : 1.15

    数独 解法一:广度优先搜索. 解法二:先填满中间矩阵,其他区域通过矩阵置换求出.

  5. BCZM : 1.9

    有n个学生参加见面会,分别对m个研究组中的若干个感兴趣,为了满足所有学生的要求,每个学生都能参加自己感兴趣的见面会,如果每个见面会的时间为t,如何安排才能使得所有见面会的总时间最短? 分析: 先建立模 ...

  6. BCZM : 1.8

    问题:      所有的员工均在1楼进电梯的时候,选择所要到达的楼层.然后计算出停靠的楼层i,当到达楼层i的时候,电梯停止.所有人走出电梯,步行到所在的楼层中.求所有人爬的楼层数目和的最小值. 解法一 ...

  7. BCZM : 1.7

    光影切割 在一个平面内有一个矩形区域,直线穿过矩形可以将其分割为不同的区域,且在这个平面中不存在三条直线相交一点的情况.求当有N条直线穿过矩形时,它被分割为多少个区域? 解法一:      平面倍划分 ...

  8. BCZM : 1.6

    https://blog.csdn.net/kabini/article/details/2311946 题目大意: 水房能容纳饮料的总量是V,有一批饮料,每种饮料单个容量都是2的方幂,每种饮料信息如 ...

  9. BCZM : 1.5

    https://blog.csdn.net/zs634134578/article/details/18046317 有很多服务器存储数据,假设一个机器仅存储一个标号为ID的记录,假设机器总量在10亿 ...

随机推荐

  1. git拉取远程所有分支

    第一步: git branch -r | grep -v '->' | while read remote; do git branch --track "${remote#origi ...

  2. 记录ajax前后交互

    前台请求 $.ajax({ url : '/turn', type : "post", data : { "userName":userName, " ...

  3. 前端学习(二十)jquery属性(笔记)

    jq里面操作属性的方法: 设置属性:            设置一个:            $(this).attr('src','img/pic2.jpg');            设置一组:  ...

  4. jQuery随机抽取数字号代码

    html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta ...

  5. openFrameworks Download

    { https://openframeworks.cc/zh_cn//download/ } 0.10.1 是最新发布的版本. 这个版本是修改了一些BUG的小版本,与版本 0.10.1100%兼容而且 ...

  6. 基础(三):yum(RedHat系列)和apt-get(Debian系列 )用法及区别

    文章转载来自:http://blog.csdn.net/chengly0129/article/details/70169760 一般来说著名的linux系统基本上分两大类:1.RedHat系列:Re ...

  7. Anaconda配置

    0x00 下载 为了更快的下载,可以到清华开源软件镜像站下载 地址:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 在此以Anaconda ...

  8. Android_开发片段(Part 3)

    1.Android中的五种布局方式:线性布局(Linear Layout).相对布局(Relative Layout).表格布局(Table Layout).网格视图(Grid View).标签布局( ...

  9. npm install 超时 国内 切换源; npm ERR! code ELIFECYCLE;

    install 超时 查看npm源地址 npm config get registry #http://registry.npmjs.org 为国外镜像地址 设置阿里云镜像 npm config se ...

  10. CentOS 搭建dns服务器 解析任意域名

    DNS服务器IP地址:192.168.1.219 服务器版本:centos6.6一:软件安装 [root@localhost ~]# yum -y install bind* 二:修改主配置文件 [r ...