计算二进制数中1出现的次数
来源:互联网 发布:2017成都软件行业 编辑:程序博客网 时间:2024/06/05 19:42
计算二进制数中1出现的次数
概述:
给定一个数,如32位的int类型的整数,由于计算机中存储都是用二进制的形式,所以计算给出的这个整数中出现1的次数
下面介绍一共五种方法:
一、mod 2
对一个整数除以2,如果整除,原来的数字就会少一个最低位的0,否则出现余数则说明最低位是1,下面给出C++代码:
//mod 2int version1(int a){ int count = 0; while (a) { count += a % 2; a /= 2; } return count;}
二、mod 2(位操作)
原理同方法一,不同的地方在于,这里的求余和除法都用了位操作来完成,下面给出C++代码:
//mod 2 with bit operationint version2(int a){ int count = 0; while (a) { count += (a & 0x00000001); a >>= 1; } return count;}
三、直接计算1出现的次数
上两种方法时间复杂度都是和数字的二进制码长度有关的,而如果二进制码长度很长而出现1的个数很少的时候,效率就不是太高,下面给出一个方法,循环次数只跟1出现的次数有关系:
//count Ones directlyint version3(int a){ int count = 0; while (a) { a &= a - 1; count ++; } return count;}
四、网上看到的一种方法
这个方法是网上看到的,他的介绍说是二分法,但是看不太懂,也放上来~好处就是会更快,因为都是位操作而且没有循环,时间复杂度就是O(1)
//bisectionint version4(int a){ a = a - ((a >> 1) & 0x55555555); a = (a & 0x33333333) + ((a >> 2) & 0x33333333); a = (a + (a >> 4)) & 0x0F0F0F0F; a = a + (a >> 8); a = a + (a >> 16); return a & 0x0000003F;}
五、查表
预先把出现1的个数记起来,存在一个数组里,不用计算,直接读取。比如先把8位的出现1的个数用数组记录下来,也就是一个256长度的数组,每个数组的元素就是对应下标的数的二进制码出现1的次数,然后把32位的int分成4段来判断,再把每个加起来,由于需要把表计算出来,这里就不写上来了~
总结
最基础的算法就是方法一,然后存在优化的地方就是把求余、除2等变成位操作,找到更低复杂度的计算方法(如一个m位的二进制数,有n位是1,则n <= m,那么能否找到O(n)而不是O(m)的方法,也或者是方法四那种更快的O(1)的方法)。虽然问题很简单,但是给我的启示就是一个优化的问题,先分析最耗费时间的部分,然后再对这个部分进行优化,循环直到达到预期为止~
0 0
- 计算二进制数中1出现的次数
- 二进制形式中1出现的次数
- 计算unsigned int型数据二进制形式中1出现的次数
- 计算1到N的十进制数中1的出现次数
- 计算1到N的十进制数中1的出现次数
- 计算1到N的十进制数中1的出现次数
- 计算1到N的十进制数中1的出现次数
- 计算1到n的数中1出现的次数
- 计算二进制数中1的个数
- 计算二进制数中1的个数
- 计算二进制数中1的个数
- 计算二进制数中1的个数
- 计算二进制数中1的个数
- 计算一个数的二进制数中1的个数
- 数组中出现次数最多的数及出现次数
- 1-n中十进制数中1出现的次数
- 计算从1到N中,1出现的次数
- 计算从1到N中1的出现次数
- tomcat远程调试
- leetcode String to Integer (atoi) java基本编程学习(二)
- CASE WHEN 及 SELECT CASE WHEN的用法
- java基于Socket设计一个Mail的收发客户端
- SQL Server 2016:内存列存储索引
- 计算二进制数中1出现的次数
- <Swift>IOS隐藏push子界面的bottom tabbar
- android的Environment类
- [Win32] API Hook(1)在32位系统上的实现
- 关于android uid 与进程的关系
- Swift array
- Android五大布局详解
- ios日期格式转换
- jackJson的基本用法3___树形读写