剑指Offer面试题:9.二进制中1的个数
一、题目:二进制中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)代码覆盖率:

剑指Offer面试题:9.二进制中1的个数的更多相关文章
- 剑指Offer - 九度1513 - 二进制中1的个数
剑指Offer - 九度1513 - 二进制中1的个数2013-11-29 23:35 题目描述: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 输入: 输入可能包含多个测试样例. ...
- 【剑指Offer】11、二进制中1的个数
题目描述: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 解题思路: 本题有以下两个解决方案: (1)依次判断每一位.判断的方法是先与1相与,为1则说明该位为1 ...
- 剑指offer 11. 位运算 二进制中1的个数
题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. //思想:用1(1自身左移运算,其实后来就不是1了)和n的每位进行位与,来判断1的个数 private stat ...
- 剑指offer(11)二进制中1的个数
题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 题目分析 首先我们要了解计算机中负数使用补码表示的,原码.补码的概念以及原理可以参考这里,这个题目我们应该从二进制入手,值得 ...
- 剑指offer【12】- 二进制中1的个数
输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. public class Solution { public int NumberOf1(int n) { String str = ...
- 剑指offer编程题Java实现——面试题10二进制中1的个数
题目: 请实现一个函数,输入一个整数,输出该整数二进制表示中1的个数.例如,把9表示成二进制是1001,有2位是1,该函数输出2解法:把整数减一和原来的数做与运算,会把该整数二进制表示中的最低位的1变 ...
- 剑指offer面试题3 二维数组中的查找(c)
剑指offer面试题三:
- 剑指offer——面试题15:二进制中 1的个数
// 面试题15:二进制中1的个数 // 题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数.例如 // 把9表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2. #inc ...
- 剑指offer面试题3二维数组中的查找
题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 需要与面试官确认的是,这 ...
- 剑指offer-面试题10:二进制中1的个数
题目:请实现一个函数,输入一个函数,输出该数二进制表示中1的个数.例如把9 表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2. 这道题最典型的方法就是用移位统计,就比如统计9的二进制1 ...
随机推荐
- 比较完整的WebView的用法
WebView, WebChromeClient和WebViewClient加载网页基本用法 webview是android中的浏览器控件,在一些手机应用中常会用到b/s模式去开发应用,这时webvi ...
- C#: using JsonReader avoid Deserialize Json to dynamic
namespace Test { using Microshaoft; using Test.Models; using Newtonsoft.Json; using System; using Sy ...
- 获取 windows 商店内的 aapx 安装包 并 安装(旁加载)
这是一篇教程,写在 win10 版<量子破碎>发售近期. 主要原因:windows 商城的应用下载实在难以忍受...... #######2016-4-9更新####### 4-6号通过旁 ...
- EXT.NET 使用总结(2) ---TreePanel(带右键菜单,节点自定义属性)
TreePanel(带右键菜单,节点自定义属性) 其实这个树控件也挺好用的.http://www.ztree.me/v3/main.php#_zTreeInfo html <ext:Panel ...
- selenium使用笔记(二)——Tesseract OCR
在自动化测试过程中我们经常会遇到需要输入验证码的情况,而现在一般以图片验证码居多.通常我们处理这种情况应该用最简单的方式,让开发给个万能验证码或者直接将验证码这个环节跳过.之前在技术交流群里也跟朋友讨 ...
- PHP多级联动的学习(一)
我尝试在ThinkCMF中实现多级联动,首先我开始看了dede的联动类别管理前后台的代码以及他的数据库,经过非常多次的尝试,我渐渐有了一点想法,并给予实施. 首先写出前台的界面.如图. 然后在数据库中 ...
- xml.etree.ElementTree对CDATA的输出
xml.etree.ElmentTree不支持CDATA 的输出,但是支持Comment的输出.由于在项目中需要输出带有CDATA块的XML文本,参考Comment的做法,修改ElmentTree中的 ...
- Python3.5 day3作业一:实现简单的shell sed替换功能
需求: 1.使python具有shell中sed替换功能. #!/usr/bin/env python #_*_conding:utf-8_*_ #sys模块用于传递参数,os模块用于与系统交互. i ...
- [WPF] 我的WPF自学日记2,自定义入口
在winform中入口文件就是Program.cs,而在WPF中看不到,因为它是自动生成的,可以说隐藏了,我们可以自定义一个入口文件,然后修改项目属性中的启动对象为我们自定义的入口文件. 首先新建入口 ...
- linux 进程通信 管道
1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管 ...