题目来源:牛客网-剑指Offer专题
题目地址:二进制中1的个数

题目描述

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

题目解析

对于这种涉及位运算的题目,我们首先要了解基本的位运算,我们可以看这篇文章:C++描述的位运算总结

(PS:本文的图例用的是8位的整数,int有32位,画出来也不美观呀)

下面先给说一种因为存在负数而错误的做法:

  • 先通过 ‘&1’ 操作来判断 nnn 的最低位否为1,若为1,则计数器 cntcntcnt 的值加1;
  • 然后利用 ‘>>1’ 操作将 nnn 右移一位;
  • 最后重复上述两步操作,直到 nnn 的值为0,得出 cntcntcnt 的值即为该数二进制表示中1的个数。

这种方法在 nnn 为正数的时候是没有问题的,因为正数进行右移操作的时,最低位舍弃,最高位补0。过程如图所示:

但是负数进行右移操作的时,最低位舍弃,最高位的是1(过程如下图),这样经过多次以后,所有数位都会变成1,进而产生死循环。

下面给大家一共四种不同的正确解法:

方法一:
利用Integer内置的toBinaryString()方法将 nnn 转换为二进制字符串,然后二进制串中的0全部消掉,最后求得的字符串长度就是该数二进制表示中1的个数。

public class Solution {public int NumberOf1(int n) {return Integer.toBinaryString(n).replaceAll("0", "").length();}
}

方法二:
这是对上面讲到的错误方法的改进,由于左移操作是最高位舍弃,最低位补0,我们选择让 nnn 不变, 对 ‘&1’ 中的1进行左移,直到移动31位为止

由上图的两种情况可以看出,当1移动了 iii 位之后,若 nnn 的第 iii 位为1,进行&运算的结果为 (1<<i)(1 << i)(1<<i),否则为0。于是,我们就可以利用他们为判断条件来计算1的个数啦~

public class Solution {public int NumberOf1(int n) {int cnt = 0;for(int i = 0; i < 32; i++) {//if ((n & (1 << i)) == (1 << i))也是可行的if ((n & (1 << i)) != 0)cnt++;}return cnt;}
}

方法三:
这种方法是很久之前zls师兄告诉我的,没想到今天才派上用场(我记忆力真好 )。

理论:nnn 和 n−1n-1n−1 进行 &\&& 运算可以把 nnn 的二进制表示的右边第一个1变成0

根据上面给的理论,我们只要知道 nnn 可以进行多少次这样的操作,就可以得到 nnn 的二进制表示中1的个数,下图以n=29为例展示这个过程:

如果对上诉过程感受不深,可以手动计算多几组数据,虽然这种方法感觉起来比较笨,但却是理解的好办法。能用上这种方法,面试应该没问题了。

public class Solution {public int NumberOf1(int n) {int cnt = 0;while (n != 0) {n = n & (n - 1);cnt++;}return cnt;}
}

方法四:
这是在牛客网评论区看到做法,由Holiday_12138发表,但是ta并没有给出具体思路,我也参悟不出来,我打算以后理解了再更新这部分,也欢迎各位大佬提供解释。(做法真的太骚了 )

public class Solution {public int  NumberOf1(int n) {int temp = n;temp = (temp & 0x55555555) + ((temp & 0xaaaaaaaa) >>> 1);temp = (temp & 0x33333333) + ((temp & 0xcccccccc) >>> 2);temp = (temp & 0x0f0f0f0f) + ((temp & 0xf0f0f0f0) >>> 4);temp = (temp & 0x00ff00ff) + ((temp & 0xff00ff00) >>> 8);temp = (temp & 0x0000ffff) + ((temp & 0xffff0000) >>> 16);return temp;}
}

如果本文对你有所帮助,要记得点赞哦~

剑指Offer #11 二进制中1的个数(想不到的骚操作)相关推荐

  1. 《LeetCode力扣练习》剑指 Offer 15. 二进制中1的个数 Java

    <LeetCode力扣练习>剑指 Offer 15. 二进制中1的个数 Java 一.资源 题目: 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ...

  2. 剑指 Offer 15. 二进制中1的个数 + 191. 位1的个数(n(n-1)实例)

    一.题目:剑指 Offer 15. 二进制中1的个数 请实现一个函数,输入一个整数(以二进制串形式),输出该数二进制表示中 1 的个数.例如,把 9 表示成二进制是 1001,有 2 位是 1.因此, ...

  3. 【LeetCode】剑指 Offer 15. 二进制中1的个数

    [LeetCode]剑指 Offer 15. 二进制中1的个数 文章目录 [LeetCode]剑指 Offer 15. 二进制中1的个数 一.逐位判断 二.巧用 n&(n−1) 一.逐位判断 ...

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

    /*** 剑指 Offer 15. 二进制中1的个数** Java Integer.bitCount 方法 源码*/public class SolutionJZ15 {public int hamm ...

  5. [剑指Offer]12.二进制中1的个数

    题目 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 思路 把一个整数减去1,再和原整数做与运算,会把整数最右边一个1变成0.那么一个整数的二进制表示中有多少个1,就可以进行多次这样 ...

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

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

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

    题目: 输入一个整数,输出该数二进制表示中1的个数 知识点: 所有进制数底层都是二进制表示,左位移1位比除二快的多 n = n & (n-1),可以依次从左到右一位一位将1转换成0 位指针左移 ...

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

    题目:输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 分析:直接使用java中的Integer自带的把一个整数转为2进制,然后数1的个数就ok(注意charAt返回的是char,用= ...

  9. 剑指offer 15.二进制中1的个数

    解法一: n & n - 1 可以让 n 最右边的 1 变为 0 ,其余位不变. class Solution { public:int hammingWeight(uint32_t n) { ...

最新文章

  1. 松耦合和紧耦合的架构设计、性能对比
  2. OpenCV创建3D直方图
  3. Windows消息机制详解-2
  4. 315. 计算右侧小于当前元素的个数
  5. QT+OpenCV综合示例:图像混合(滑动条)
  6. vmware虚拟机里的服务器自动关闭,让VirtualBox虚拟机在主机关闭时自动关闭或保存状态VBoxVmService...
  7. hadoop2.0初识1.2
  8. rss feed for testing
  9. 周边pd是什么意思_pd是什么意思 饭圈pd是什么意思
  10. 世界三大统计分析软件sas splus spss
  11. 51单片机——外部中断
  12. 云计算之存储虚拟化 -02
  13. windows+中标麒麟双系统启动优先顺序调整方法
  14. 红米5无线网连接上但是没有网络连接服务器,红米路由器wifi已连接但无法访问互联网怎么办 | 192路由网...
  15. Day14:网络编程入门
  16. Spring_7_AOP之Advice应用
  17. 【彻底解决】谷歌或Edge浏览器登录谷歌账户提示浏览器不安全请重新登录
  18. 北大计算机专业年薪,清华、北大毕业生的年薪全国最高吗?一般能达到多少?...
  19. 船东提单和货代提单差距这么大?
  20. 关于nslookup 网址 一直出现unknown的问题排查

热门文章

  1. 验证异常处理调用顺序
  2. 正则表达式,解决要么有要有没有,但必须开头
  3. 操作系统是如何使用重定位表的
  4. C语言的结构使用和结构对齐
  5. angr学习笔记(10)(hook)
  6. 11.分页(10-10-12)
  7. 1.段描述符与段选择子
  8. 5、优化MySQL服务器
  9. 验证网站地址是否有效
  10. 寒假每日一题2022【week1 完结】