本文参考自《剑指offer》一书,代码采用Java语言。

更多:《剑指Offer》Java实现合集  

题目

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

思路

  遇到与二进制有关的题目,应该想到位运算(与、或、异或、左移、右移)。

  方法一:”与运算“有一个性质:通过与对应位上为1,其余位为0的数进行与运算,可以某一整数指定位上的值。这道题中,先把整数n与1做与运算,判断最低位是否为1;接着把1左移一位,与n做与运算,可以判断次低位是否为1……反复左移,即可对每一个位置都进行判断,从而可以获得1的个数。这种方法需要循环判断32次。

  方法二(better):如果一个整数不为0,把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1。其余所有位将不会受到影响。再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。因此,把一个整数减1,再和原来的整数做与运算,会把该整数最右边的1变成0。这种方法,整数中有几个1,就只需要循环判断几次。

测试用例

  1.正数(包括边界值1、0x7FFFFFFF)

  2.负数(包括边界值0x80000000、0xFFFFFFFF)

  3.0

完整Java代码

(含测试代码)

/**
*
* @Description 面试题15:二进制中1的个数
*
* @author yongh
* @date 2018年9月17日 下午3:01:16
*/ // 题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如
// 把9表示成二进制是1001,有2位是1。因此如果输入9,该函数输出2。 public class NumberOf1InBinary {
public int NumberOf1_Solution1(int n) {
int count = 0;
int flag = 1;
while (flag != 0) {
if ((flag & n) != 0)
count++;
flag = flag << 1;
}
return count;
} public int NumberOf1_Solution2(int n) {
int count = 0;
while (n != 0) {
count++;
n = (n - 1) & n;
}
return count;
} // =========测试代码========= void test(String testName, int n, int expected) {
if (testName != null)
System.out.println(testName + ":");
if (NumberOf1_Solution1(n) == expected) {
System.out.print(" soluton1:" + "passed ");
} else {
System.out.print(" solution1:" + "failed ");
} if (NumberOf1_Solution2(n) == expected) {
System.out.println("soluton2:" + "passed ");
} else {
System.out.println("solution2:" + "failed ");
}
} void test1() {
test("Test for 0", 0, 0);
} void test2() {
test("Test for 1", 1, 1);
} void test3() {
test("Test for 10", 10, 2);
} void test4() {
test("Test for 0x7FFFFFFF", 0x7FFFFFFF, 31);
} void test5() {
test("Test for 0xFFFFFFFF", 0xFFFFFFFF, 32);
} void test6() {
test("Test for 0x80000000", 0x80000000, 1);
} public static void main(String[] args) {
NumberOf1InBinary demo = new NumberOf1InBinary();
demo.test1();
demo.test2();
demo.test3();
demo.test4();
demo.test5();
demo.test6();
}
}

    

Test for :
soluton1:passed soluton2:passed
Test for :
soluton1:passed soluton2:passed
Test for :
soluton1:passed soluton2:passed
Test for 0x7FFFFFFF:
soluton1:passed soluton2:passed
Test for 0xFFFFFFFF:
soluton1:passed soluton2:passed
Test for 0x80000000:
soluton1:passed soluton2:passed

NumberOf1InBinary

收获

  1.与二进制有关的题目要往位运算方面想,复习一下:二进制位运算的几个用法

  2.注意:负数右移还是负数!即如果对n=0x8000 0000右移,最高位的1是不会变的。如果这道题目通过令n=n>>1来计算n中1的个数,该数最终会变成0xFFFF FFFF而陷入死循环!

  3.把一个整数减1,再和原来的整数做与运算,会把该整数最右边的1变成0。这种方法一定要牢牢记住,很多情况下都可能用到,例如:

   1)一句话判断一个整数是否为2的整数次方;

   2)对两个整数m和n,计算需要改变m二进制表示中的几位才能得到n。

  4.与数字操作有关的题目,测试时注意边界值的问题。对于32位数字,其正数的边界值为1、0x7FFFFFFF,负数的边界值为0x80000000、0xFFFFFFFF。

  5.几个细节问题

   1)flag=flag<<1,而不是只写一句flag<<1;

   2)flag&n!=0,而非flag&n==1; 也就不能写成count+=(flag&1)了

   3)if语句中,不能写为if(flag&n!=0) ,而要写成 if((flag&n)!=0),需要注意一下

更多:《剑指Offer》Java实现合集  

【Java】 剑指offer(14) 二进制中1的个数的更多相关文章

  1. 《剑指offer》 二进制中1的个数

    本题来自<剑指offer> 二进制中1的个数 题目: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 思路: 两种思路: 第一种:对n进行左移,检测最后一位是否为1,但考 ...

  2. 剑指 Offer 15. 二进制中1的个数

    剑指 Offer 15. 二进制中1的个数 Offer 15 题目描述: 方法一:使用1逐位相与的方式来判断每位是否为1 /** * 方法一:使用1逐位与的方法 */ public class Off ...

  3. 刷题-力扣-剑指 Offer 15. 二进制中1的个数

    剑指 Offer 15. 二进制中1的个数 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de- ...

  4. 剑指Offer:二进制中1的个数

    题目:输入一个整数,输出该数二进制表示中1的个数. // 二进制中1的个数 #include <stdio.h> int wrong_count_1_bits(int n) // 错误解法 ...

  5. Go语言实现:【剑指offer】二进制中1的个数

    该题目来源于牛客网<剑指offer>专题. 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 分析: 如果一个整数不为0,那么这个整数至少有一位是1.如果我们把这个整数减1 ...

  6. 剑指offer例题——二进制中1的个数

    题目:输入一个整数,输出该二进制表示中1的个数.其中负数用补码表示. 首先明确补码的定义: 原码 反码 补码 将最高位作为符号位(0表示正,1表示负), 其它数字位表达数值本身的绝对值的数字表示方式 ...

  7. 剑指offer 11二进制中1的个数

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

  8. 《剑指offer》二进制中1的个数

    一.题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 二.牛客网提供的框架 class Solution { public: int NumberOf1(int n) { } ...

  9. 剑指Offer之二进制中1的个数

    题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示.     解法1:使用Integer.toBinanryString()返回int变量的二进制表示的字符串. [在Intege ...

随机推荐

  1. SQL Server 2008“备份集中的数据库备份与现有的数据库不同”解决方法

    对于SQL Server 2008,有几个地方是要注意的,比方在还原数据库时,不像2000里边将数据库和文件区分的很细, 统一均为文件,这就使还原的数据库文件制定为. bak.那么想还原2000的数据 ...

  2. 【IT界的厨子】酱香鲈鱼

    食材: 前世曾经回眸的鲈鱼一条(主要选刺少的鱼,适合孩子吃,大人吃随意,草鱼比较大) 五花肉少许(肥一些的) 豆腐 辅料: 葱姜 蒜(选) 大料 香菜 调味: 啤酒(两罐) 黄豆酱或豆瓣酱(选) 老抽 ...

  3. 课程4:黑马程序员_spring2.5视频教程--视频列表

    \黑马程序员_spring2.5视频教程\01Struts相关基础理论介绍.mp4; \黑马程序员_spring2.5视频教程\02搭建struts开发环境.mp4; \黑马程序员_spring2.5 ...

  4. python - class类 (七) 三大特性 - 封装 结尾

    封装: # 封装 #第一层,类就是麻袋,本身就是一种封装 #第二层,类中定义私有的,至在类的内部使用,外部无法访问 #第三层,封装在于明确区分内外,使得类实现者可以修改封装内的东西二不影响外部调用者 ...

  5. script标签中type为"text/x-template"或"text/html"

    写过一点前端的都会碰到需要使用JS字符串拼接HTML元素然后append到页面DOM树上的情况,一般的写法都是使用+号以字符串的形式拼接,如果是短点的还好,如果很长很长的话就会拼接到令人崩溃了. 比如 ...

  6. SpringBoot2.x过滤器Filter和使用Servlet3.0配置自定义Filter实战

    补充:SpringBoot启动日志 1.深入SpringBoot2.x过滤器Filter和使用Servlet3.0配置自定义Filter实战(核心知识) 简介:讲解SpringBoot里面Filter ...

  7. JavaScript对象复制(二)

    <script> function copy(a) { ret = {}; for (sth in a) { temp = a[sth]; if (temp instanceof Arra ...

  8. 3种shell自动交互的方法【转】

    一.背景 shell脚本在处理自动循环或大的任务方面可节省大量的时间,通过创建一个处理任务的命令清单,使用变量.条件.算术和循环等方法快速创建脚本以完成相应工作,这比在命令行下一个个敲入命令要省时省力 ...

  9. css 悬浮框

    <style>    .xfk {        display: block;        position: fixed;        top: 150px;        lef ...

  10. Ext.util.Format.date与Ext.Date.format区别, 转换时间戳

    在Extjs中装时间戳使用如下两种都可以: Ext.util.Format.date(time,'U'); Ext.Date.format(time, 'U'); 为了找到它们的区别,查看源代码,以E ...