一、题目:二进制中1的个数

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

二、可能引起死循环的解法

  一个基本的思路:先判断整数二进制表示中最右边一位是不是1。接着把输入的整数右移一位,此时原来处于从右边数起的第二位被移到最右边了,再判断是不是1。这样每次移动一位,直到整个整数变成0为止。

  怎么判断一个整数的最右边是不是1:只要把整数和1做位与运算看结果是不是0就知道了

    public static int NumberOf1Solution1(int n)
{
int count = ; while (n > )
{
if ((n & ) == )
{
count++;
} n = n >> ;
} return count;
}

PS:右移运算符m>>n表示把m右移n位。右移n位的时候,最右边的n位将被丢弃。如果数字原先是一个正数,则右移之后在最左边补n个0;如果数字原先是负数,则右移之后在最左边补n个1。例如下面对两个八位二进制数进行右移操作:

00001010>>2=00000010

10001010>>3=11110001

那么,问题来了:上面的方法如果输入一个负数,比如0x80000000,如果一直做右移运算,最终这个数字就会变成0xFFFFFFFF而陷入死循环

三、避免引起死循环的解法

  为了避免死循环,我们可以不右移输入的数字i:

  (1)首先把i和1做与运算,判断i的最低位是不是为1。

  (2)接着把1左移一位得到2,再和i做与运算,就能判断i的次低位是不是1。

  (3)这样反复左移,每次都能判断i的其中一位是不是1。

    public static int NumberOf1Solution2(int n)
{
int count = ;
uint flag = ;
while (flag >= )
{
if ((n & flag) > )
{
count++;
} flag = flag << ;
} return count;
}

PS:这个解法中循环的次数等于整数二进制的位数,32位的整数需要循环32次。

四、高效新颖的解法

  把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。

    public static int NumberOf1Solution3(int n)
{
int count = ; while (n > )
{
count++;
n = (n - ) & n;
} return count;
}

PS:把一个整数减去1之后再和原来的整数做位与运算,得到的结果相当于是把整数的二进制表示中的最右边一个1变成0。很多二进制的问题都可以用这个思路解决。

五、单元测试

5.1 测试用例

    // 输入0,期待的输出是0
[TestMethod]
public void NumberOfOneInBinaryTest1()
{
Assert.AreEqual(BinaryHelper.NumberOf1Solution2(),);
Assert.AreEqual(BinaryHelper.NumberOf1Solution3(),);
} // 输入1,期待的输出是1
[TestMethod]
public void NumberOfOneInBinaryTest2()
{
Assert.AreEqual(BinaryHelper.NumberOf1Solution2(), );
Assert.AreEqual(BinaryHelper.NumberOf1Solution3(), );
} // 输入10,期待的输出是2
[TestMethod]
public void NumberOfOneInBinaryTest3()
{
Assert.AreEqual(BinaryHelper.NumberOf1Solution2(), );
Assert.AreEqual(BinaryHelper.NumberOf1Solution3(), );
} // 输入0x7FFFFFFF,期待的输出是31
[TestMethod]
public void NumberOfOneInBinaryTest4()
{
Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0x7FFFFFFF), );
Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0x7FFFFFFF), );
} // 输入0xFFFFFFFF(负数),期待的输出是32
[TestMethod]
public void NumberOfOneInBinaryTest5()
{
Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0xFFFFFFFF), );
Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0xFFFFFFFF), );
} // 输入0x80000000(负数),期待的输出是0
[TestMethod]
public void NumberOfOneInBinaryTest6()
{
Assert.AreEqual(BinaryHelper.NumberOf1Solution2(0x80000000), );
Assert.AreEqual(BinaryHelper.NumberOf1Solution3(0x80000000), );
}

5.2 测试结果

  (1)测试通过情况:

  (2)代码覆盖率:

作者:周旭龙

出处:http://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

剑指Offer面试题:9.二进制中1的个数的更多相关文章

  1. 剑指Offer - 九度1513 - 二进制中1的个数

    剑指Offer - 九度1513 - 二进制中1的个数2013-11-29 23:35 题目描述: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 输入: 输入可能包含多个测试样例. ...

  2. 【剑指Offer】11、二进制中1的个数

      题目描述:   输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示.   解题思路:   本题有以下两个解决方案:   (1)依次判断每一位.判断的方法是先与1相与,为1则说明该位为1 ...

  3. 剑指offer 11. 位运算 二进制中1的个数

    题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示.   //思想:用1(1自身左移运算,其实后来就不是1了)和n的每位进行位与,来判断1的个数     private stat ...

  4. 剑指offer(11)二进制中1的个数

    题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 题目分析 首先我们要了解计算机中负数使用补码表示的,原码.补码的概念以及原理可以参考这里,这个题目我们应该从二进制入手,值得 ...

  5. 剑指offer【12】- 二进制中1的个数

    输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. public class Solution { public int NumberOf1(int n) { String str = ...

  6. 剑指offer编程题Java实现——面试题10二进制中1的个数

    题目: 请实现一个函数,输入一个整数,输出该整数二进制表示中1的个数.例如,把9表示成二进制是1001,有2位是1,该函数输出2解法:把整数减一和原来的数做与运算,会把该整数二进制表示中的最低位的1变 ...

  7. 剑指offer面试题3 二维数组中的查找(c)

    剑指offer面试题三:

  8. 剑指offer——面试题15:二进制中 1的个数

    // 面试题15:二进制中1的个数 // 题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数.例如 // 把9表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2. #inc ...

  9. 剑指offer面试题3二维数组中的查找

    题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 需要与面试官确认的是,这 ...

  10. 剑指offer-面试题10:二进制中1的个数

    题目:请实现一个函数,输入一个函数,输出该数二进制表示中1的个数.例如把9 表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2. 这道题最典型的方法就是用移位统计,就比如统计9的二进制1 ...

随机推荐

  1. Redis3重建Cluster

    1.关闭cluster全部节点2.删除所有nodes.conf文件3.开启全部节点4.依次flushall5.重建集群即可 Share the post "Redis3重建Cluster&q ...

  2. linux简单命令

    查看服务器开启的进程信息[root@CentOSHT ~]# top 其中第一行的  Load average 参数是服务器负载的意思,

  3. 定时脚本: 删除HDFS中的过期文件

    1. 基本原理: 通过hadoop fs -ls *命令获取相关文件或目录的修改时间,然后与设定的过期时间进行比较,之后执行删除操作即可 2. 相关代码: #!/bin/bash source ~/. ...

  4. swift - 字典和集合

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #4dbf56 } p.p2 { margin: 0.0px 0. ...

  5. [vue案例的知识点]todo-list

    文章的原材料来自于vue的官方示例:https://cn.vuejs.org/v2/examples/todomvc.html,我们在学习过程中,试着对其中的一些知识点进行记录: 一.浏览器数据存储, ...

  6. 【面试题】D

    一面: 1.介绍实习项目,负责那一部分: 2.C++的三大特性: 3.7层网络协议:应用层协议有哪些,TCP/IP属于哪一层,三次握手: 4.Linux: 4.1.查看进程: 4.2.vim文件与to ...

  7. 用Fiddler的自动响应模拟系统集成

    1. 下载最新版本的Fiddler Fiddler 官网 2, 安装并启动Fiddler 3, 勾选自动响应 见上图 4, 添加自动响应规则 见上图 5, 添加自动响应内容文件 添加响应文件到Fidd ...

  8. spark 2.0 中 pyspark 对接 Ipython

    pyspark 2.0 对接 ipython 在安装spark2.0 后,以往的对接ipython方法失效,会报如下错错误: 因为在spark2.0后对接ipython的方法进行了变更我们只需要在py ...

  9. [软件推荐]快速文件复制工具(Limit Copy) V4.0 绿色版

    快速文件复制工具(Limit Copy)绿色版是一款智能变频超快复制绿色软件. 快速文件复制工具(Limit Copy)功能比较完善,除了文件复制还可以智能变频,直接把要复制的文件拖入窗口即可,无需手 ...

  10. jQuery插件开发(溢出滚动)

    声明:此程序仅针对手机端,简单的封装一个插件,意在记载插件的开发过程,如有错误及不足之处,还望即时指出. 移动开发的时候,我们经常会遇到滑动事件,众所周知手机端滑动主要依靠touch事件.最近接连遇到 ...