一、题目:二进制中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. tmpfs详解

    一,tmpfs介绍 1. tmpfs是一种虚拟内存文件系统,正如这个定义它最大的特点就是它的存储空间在VM里面(什么是VM?后面介绍) 2. VM是由linux内核里面的vm子系统管理的东西,现在大多 ...

  2. x

    笔记 { 计算机 { 底层 { 程序运行 } 信息学 { 网络 { 网络信息安全 } 算法 { 算法 拟合 编译解释词法分析 } 编程语言 { C语言 嵌入式C++ } 黑客 } } 安卓 { 软件 ...

  3. 安装DRools开发环境

    1.下载相关安装包和开发插件 网站:http://www.jboss.org/drools/downloads.html 1.1 drools-distribution-6.3.0.Final.zip ...

  4. 常见css水平自适应布局

    左右布局,左边固定,右边自适应布局 BFC方法解决 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...

  5. <HTML>菜鸟入门基础须知

    将持续更新-- 一,基础常用标签and属性 既然要学习这门知识,那必须得先知道这是什么能做什么,HTML:是一种超文本标记语言,什么意思呢,我拆开看一下,超(超链接)文本(犹如TXT)标记(改变成自己 ...

  6. 矩阵快速幂 HDU 4565 So Easy!(简单?才怪!)

    题目链接 题意: 思路: 直接拿别人的图,自己写太麻烦了~ 然后就可以用矩阵快速幂套模板求递推式啦~ 另外: 这题想不到或者不会矩阵快速幂,根本没法做,还是2013年长沙邀请赛水题,也是2008年Go ...

  7. JS+CSS 钟表

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

  8. BZOJ1129 : [POI2008]Per

    枚举LCP,假设前$i-1$个都相同.那么后面$n-i$个数可以随意排列,第$i$个位置可以填的方案数为后面小于$a_i$的数字个数,树状数组维护. 同时为了保证本质不同,方案数需要除以每个数字的个数 ...

  9. 关于这个博客以及C++入门该懂的一些东西

    给三牧中学c++入门的同学们看的博客. 大概是入门一类的?说不定会写点自己的结题报告. 写的不好/写错了别怪我,蒟蒻瑟瑟发抖. 天哪要开始写入门了我好慌那么接下来是编译器连接. (本蒟蒻喜欢用DEV ...

  10. shell脚本生成限定范围的随机数

    #!/bin/bash +)) 这串代码实现了随机生成从1~50之间是数 这串代码特别简单,就是利用RANDOM这个随机数生成器进行取余就能够实现,至于为什么取余时需要+1是因为在取余时如果被整除那么 ...