BCZM : 2.1
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的更多相关文章
- BCZM: Chapter 2
2.1 二进制数中 1 的个数 实现一个函数,输入一个无符号整数,输出该数二进制中的1的个数.例如把9表示成二进制是1001,有2位是1,因此如果输入9,该函数输出2 分析与解法 解法1:利用十进制和 ...
- BCZM: Chapter 1
1.1 CPU 占用率 https://www.cnblogs.com/TenosDoIt/p/3242910.html 1.2 中国象棋将帅 https://blog.csdn.net/kabini ...
- BCZM : 1.16
24点游戏 解法一:穷举法 解法二:分治法
- BCZM : 1.15
数独 解法一:广度优先搜索. 解法二:先填满中间矩阵,其他区域通过矩阵置换求出.
- BCZM : 1.9
有n个学生参加见面会,分别对m个研究组中的若干个感兴趣,为了满足所有学生的要求,每个学生都能参加自己感兴趣的见面会,如果每个见面会的时间为t,如何安排才能使得所有见面会的总时间最短? 分析: 先建立模 ...
- BCZM : 1.8
问题: 所有的员工均在1楼进电梯的时候,选择所要到达的楼层.然后计算出停靠的楼层i,当到达楼层i的时候,电梯停止.所有人走出电梯,步行到所在的楼层中.求所有人爬的楼层数目和的最小值. 解法一 ...
- BCZM : 1.7
光影切割 在一个平面内有一个矩形区域,直线穿过矩形可以将其分割为不同的区域,且在这个平面中不存在三条直线相交一点的情况.求当有N条直线穿过矩形时,它被分割为多少个区域? 解法一: 平面倍划分 ...
- BCZM : 1.6
https://blog.csdn.net/kabini/article/details/2311946 题目大意: 水房能容纳饮料的总量是V,有一批饮料,每种饮料单个容量都是2的方幂,每种饮料信息如 ...
- BCZM : 1.5
https://blog.csdn.net/zs634134578/article/details/18046317 有很多服务器存储数据,假设一个机器仅存储一个标号为ID的记录,假设机器总量在10亿 ...
随机推荐
- nodejs模块——fs模块 WriteFile写入文件
WriteFile写入文件 使用fs.writeFile(filename,data,[options],callback)写入内容到文件. 参数说明: filename String 文件名 dat ...
- PHP FILTER_SANITIZE_MAGIC_QUOTES 过滤器
定义和用法 FILTER_SANITIZE_MAGIC_QUOTES 过滤器对字符串执行 addslashes() 函数. 该过滤器在预定义的字符串前面设置反斜杠. 预定义字符是: 单引号(') 双引 ...
- Android 在OnCreate()中获取控件高度与宽度
试过在OnCreate()中获取控件高度与宽度的童鞋都知道,getWidth()与getHeight()方法返回是0,具体原因 看一下Activity的生命周期 就会明白. 上代码: 方法一: int ...
- 折半枚举——poj3977
暴力搜索超时,但是折半后两部分状态支持合并的情况,可用折半枚举算法 poj3977 给一个序列a[],从里面找到k个数,使其和的绝对值最小 经典折半枚举法+二分解决,对于前一半数开一个map,map[ ...
- Likecloud-吃、吃、吃
题目背景 问世间,青春期为何物? 答曰:"甲亢,甲亢,再甲亢:挨饿,挨饿,再挨饿!" 题目描述 正处在某一特定时期之中的李大水牛由于消化系统比较发达,最近一直处在饥饿的状态中.某日 ...
- Python内置模块-time && datatime
Python提供两种时间表示方式,一种是时间戳,从1970年1月1日 0时开始.一种是struct_time数组格式,共有9个元素. import time print(time.time()) #返 ...
- JAVA并发工具类---------------(Fork/Join)
Fork/Join 分而治之 将一个大任务分成数个小任务执行,然后将这些小人物执行后的结果进行join汇总: (假设:你要计算1到1000的总和,你可以把它分成1-100,101-200,...... ...
- 如何在一个for语句中迭代多个对象(2.7)
如何在一个for语句中迭代多个对象 总结: 并行迭代使用zip(l1, l2, l3) 每次迭代从3个列表里各取一个数据 串行迭代使用itertools.chain(l1, l2, l3) 相当于把3 ...
- 关于ios 的耳机线线控
如题 线控主要就是指的用ios耳机的 中间那个键来自定义一些程序自己的事件(比如玩吃鸡的时候,作为开枪扳机) 而想要控制耳机的音量加减的事件, 有一种方法,就是监听 系统音量的变化,根据音量变化来触 ...
- 杂项-PPT:如何把幻灯片ppt转换成视频
ylbtech-杂项-PPT:如何把幻灯片ppt转换成视频 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 1. https://jingyan.baidu.co ...