转:http://toutiao.com/a4280977370/

【解法一】

可以举一个八位的二进制例子来进行分析。对于二进制操作,我们知道,除以一个 2,原来的数字将会减少一个0。如果除的过程中有余,那么就表示当前位置有一个1。以 10 100 010 为例;第一次除以 2 时,商为1 010 001,余为0。第二次除以 2 时,商为101 000,余为1。因此,可以考虑利用整型数据除法的特点,通过相除和判断余数的值来进行分析。于是有了如下的代码。

代码清单 2-1

【解法二】使用位操作

前面的代码看起来比较复杂。我们知道,向右移位操作同样也可以达到相除的目的。唯一不同之处在于,移位之后如何来判断是否有1 存在。对于这个问题,再来看看一个八位的数字:10 100 001。在向右移位的过程中,我们会把最后一位直接丢弃。因此,需要判断最后一位是否为1,而“与”操作可以达到目的。可以把这个八位的数字与00000001 进行“与”操作。如果结果为1,则表示当前八位数的最后一位为1,否则为0。代码如下:

代码清单 2-2

【解法三】

位操作比除、余操作的效率高了很多。但是,即使采用位操作,时间复杂度仍为O(log2v),log2v 为二进制数的位数。那么,还能不能再降低一些复杂度呢?如果有办法让算法的复杂度只与“1”的个数有关,复杂度不就能进一步降低了吗?同样用 10 100 001 来举例。如果只考虑和1 的个数相关,那么,我们是否能够在每次判断中,仅与1 来进行判断呢?为了简化这个问题,我们考虑只有一个 1 的情况。例如:01 000 000。如何判断给定的二进制数里面有且仅有一个 1 呢?可以通过判断这个数是否是2 的整数次幂来实现。另外,如果只和这一个“1”进行判断,如何设计操作呢?我们知道的是,如果进行这个操作,结果为0 或为1,就可以得到结论。如果希望操作后的结果为 0,01 000 000 可以和00 111 111 进行“与”操作。这样,要进行的操作就是 01 000 000 &(01 000 000 – 00 000 001)= 01 000 000 &00 111 111 = 0。因此就有了解法三的代码:

代码清单 2-3

最后,得到解法四:算法中不需要进行任何的比较便可直接返回答案,这个解法在时间复杂度上应该能够让人高山仰止了。

【解法四】查表法

代码清单 2-5

这是个典型的空间换时间的算法,把0~255 中“1”的个数直接存储在数组中,v 作为数组的下标,countTable[v]就是v 中“1”的个数。算法的时间复杂度仅为O(1)。在一个需要频繁使用这个算法的应用中,通过“空间换时间”来获取高的时间效率是一个常用的方法,具体的算法还应针对不同应用进行优化。

转:对于一个字节(8bit)的变量,求其二进制表示中“1”的个数的更多相关文章

  1. int abs(int number)函数有感: 求补码和通过补码求对应的整数 C++(增加:数字的二进制表示中1的个数)

    #include "limits.h" #include "math.h" int abs(int number) { int const mask = num ...

  2. 剑指offer11:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。(进制转换,补码反码)

    1. 题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 2. 思路和方法 使用移位(<<)和 “| & !”操作来实现.1的二进制是:前面都是0,最后一位 ...

  3. Leetcode 给一个数a和一个向量b,找出该向量b中的2个数相加等于a,并输出这两个数在向量中的位置

    看C++primer Plus看的无聊,第一次做Leetcode的练习,本来想做二维向量的,结果始终通不过,查了原因,必须用一维的... 一维的答案: class Solution {  public ...

  4. C++ 一个整数的二进制表示中1的个数

    想知道某一位是否为1,只需和当前位对应的2的幂进行按位与运算即可. 如下示例,可以知道第6位是1,同理可知其他位是否为1,累加就能得到1的个数: 10001001 00000000 int cnt = ...

  5. 在8086中,[ idata],[bx]表示内存单元时。可能是一个字节,也可能是一个字。

    可能表示一个字节,也可能表示一个字.主要由指令中另一个计算对象决定.如al表示一个字节.ax就表示一个字. 这个区别主要体现在循环中,偏移地址的循环变量是加1还是加2,al是偏移地址加1,ax是偏移地 ...

  6. java编程基础篇---------> 编写一个程序,从键盘输入三个整数,求三个整数中的最小值。

    编写一个程序,从键盘输入三个整数,求三个整数中的最小值. 关键:声明变量temp   与各数值比较. package Exam01; import java.util.Scanner; public ...

  7. VC中出现“烫”和“屯”的原因(栈区的每一个字节都被0xCC填充了,也就是int 3h的机器码,动态分配的堆,VC的Debug用0xCD填充堆的空间,就出现了“屯”)

    相信经常用VC的朋友对屏幕输出的一大堆“烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”不会陌生,但是也许会很奇怪,为什么会出现“烫”字呢?莫非改程序导致系统运行缓慢,发热过高???非也!下面让我解释 ...

  8. Mysql-Innodb : 从一个字节到整个数据库表了解物理存储结构和逻辑存储结构

    首先要从Innodb怎么看待磁盘物理空间说起   一块原生的(Raw)物理磁盘,可以把他看成一个字节一个字节单元组成的物理存储介质   如果要在这块原生物理空间中插入一条记录,不能单单只插入数据,还需 ...

  9. 使用context来传递数据,一个context是一系列变量

    页面设计工作和python代码分离,所以我们引用模板来实现这个功能. 一.模板实例 下面是一个模板的实例: [python]<html><head><title>O ...

随机推荐

  1. Java被忽略的基本知识(二)

    14.字符串的内容不可改变,不能修改某个下标的字符值.字符串之间的"+"连接是通过"断开--再连接",修改变量的栈中的引用地址指向. 15.对于数组.类(类的属 ...

  2. MATLAB绘图

    matlab绘制散点图 clc,clear x=[11.9,11.5,14.5,15.2,15.9,16.3,14.6,12.9,15.8,14.1]; y=[196.84,196.84,197.14 ...

  3. SSH框架使用中存在的诡异异常

    背景 相信大多数人目前都在使用Spring + Struts2/SpringMVC + Hibernate来构建项目的整体架构,但是在使用中经藏会遇到一些诡异的问题,不知道如果解决,今天我遇到了一个非 ...

  4. SSAS中事实表中的数据如果因为一对多或多对多关系复制了多份,在维度上聚合的时候还是只算一份

    SSAS事实表中的数据,有时候会因为一对多或多对多关系发生复制变成多份,如下图所示: 图1 我们可以从上面图片中看到,在这个例子中,有三个事实表Fact_People_Money(此表用字段Money ...

  5. Oracle sql语句执行顺序

    sql语法的分析是从右到左 一.sql语句的执行步骤: 1)词法分析,词法分析阶段是编译过程的第一个阶段.这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构 ...

  6. java语言的I/O操作预习

    一些概念: 流:计算机的输入输出之间流动的数据序列,也是类的对象.java中的流方式就像是建立在数据交换源和目的之间的一条通信路径. 数据源:计算机中的数据源是指可以提供数据的地方,包括键盘,磁盘文件 ...

  7. maven nexus 私服的搭建学习

    之前对maven有过初步的了解与认识,自己也创建过项目使用其来管理,但都是非常粗浅的操作,今天在高人的指点下,也学着在自己的电脑上搭建一个maven私服,虽然技术难度也不高,但为了更深层次的提高,这些 ...

  8. 设置button键隐藏文字text

     新手的第一天,从最简单的view开始做起.首先先来做个最简单的button携带不可见文本,想要的时候,get它就行了. 编程的都知道,get .set方法,就不多介绍了. 创建一个类,MyButto ...

  9. centos7下搭建nginx+php7.1+mariadb+memcached+redis

    一.环境准备 1.首先介绍一下环境,以及我们今天的主角们 我用的环境是最小化安装的centos7,mariadb(江湖传言mysql被oracle收购后,人们担心像java一样毁在oracle手上于是 ...

  10. android 弹出对话框之四周变暗处理方式

    设置对话框的dim值即可 WindowManager.LayoutParams lp=popDlg.getWindow().getAttributes(); lp.dimAmount = 0.0f; ...