本文参考自《剑指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. 七、uboot 代码流程分析---C环境建立

    7.1 start.S 修改 在上一节中的流程中,发现初始化的过程并没由设置看门狗,也未进行中断屏蔽 如果看门狗不禁用,会导致系统反复重启,因此需要在初始化的时候禁用看门狗:中断屏蔽保证启动过程中不出 ...

  2. ettercap中间人攻击--参数介绍

    攻击和嗅探  -M,  --mitm ARP欺骗,参数 -M arp remote    # 双向模式,同时欺骗通信双方,-M arp:remote. oneway   #单向模式,只arp欺骗第一个 ...

  3. CSS——margin

    CSS margin 属性 定义和用法 margin 简写属性在一个声明中设置所有外边距属性.该属性可以有 1 到 4 个值. 说明 这个简写属性设置一个元素所有外边距的宽度,或者设置各边上外边距的宽 ...

  4. Java开发中各种集合框架简介

    在大数据MapReduce作业开发中,我们经常会遇到一些大小表的join,这是如果这个小表足够“小”的话,我们可以使用进行“map-join-side”,这要就可以有效的降低reduce端的压力,但是 ...

  5. C++中路径的处理方法(string)

    string 类提供字符串处理函数,利用这些函数,程序员可以在字符串内查找字符,提取连续字符序列(称为子串),以及在字符串中删除和添加.我们将介绍一些主要函数. 1.函数find_first_of() ...

  6. Java EE之Hibernate的HibernateSessionFactory

    昨天,一下午都被一个bug缠身,最后逐层排查,发现是MyEclipse 2014自动生成的HibernateSessionFactory有问题.后观察网友提供的自动生成的HibernateSessio ...

  7. luogu P1486 [NOI2004]郁闷的出纳员

    一万年以后终于调过了这题 这道题主要是维护一个有序的集合(吧),所以使用平衡树(我这里用\(Splay\)) 记录一个变量\(ff\)(雾),表示所有工资的变化量 对于\(I\)操作,如果初始工资大于 ...

  8. POJ 1061 青蛙的约会 (扩展欧几里得算法)

    题目链接 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件 ...

  9. _vimrc(VimScript脚本语言学习)

    Windows下 syntax on "高亮 "缩进 set cindent "set cin set smartindent "set si set auto ...

  10. 【vue报错】——listen EADDRINUSE :::8080 解决方案

    题原因: 此项错误表示 8080 端口被占用 解决方案一: 打开cmd输入:netstat -ano|findstr "8080"查看所有端口信息,并通过findstr “8080 ...