当前位置: 首页 > news >正文

二进制中1的个数 -- java

题目描述

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

题目考点

考察应聘者对二进制及位运算的理解。

解题思路

常规解法

首先把n和1做与运算,判断n的最低位是不是为1,接着把1左移一位得到2,再和n做运算,就能判断n的次低位是不是1…这样反复左移,每次都能判断n的其中一位是不是1。

能给面试官带来惊喜的解法

我们基于这样一个事实:把一个整数减去1之后再后原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的1变成0

例子如下:

n       : 10110100
n-1     : 10110011
n&(n-1) : 10110000

那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。

Java自带API解法

Integer.bitCount(n);

代码

常规解法

public class NumberOf1 {
    public static int numberOf1(int n) {
        int count = 0;
        int flag = 1;
        while (flag != 0) {
            if ((n & flag) != 0) {
                count++;
            }

            flag = flag << 1;
        }
        return count;
    }

    public static void main(String[] args) {
        System.out.println(numberOf1(9));
    }
}

能给面试官带来惊喜的解法

public class NumberOf1 {
    public static int numberOf1(int n) {
        int count = 0;
        while (n != 0) {
            count++;
            n = n & (n-1);
        }
        return count;
    }

    public static void main(String[] args) {
        System.out.println(numberOf1(9));
    }
}

补充

位运算只有5种运算:与、或、异或、左移和右移。

与、或、异或运算就是简单的真值表。

左移运算符 m<<n 表示把 m 左移 n 位。在左移 n 位的时候,最左边的 n 位将被丢弃,同时在最右边补上 n 个0.

右移运算符 m>>n 表示把 m 右移 n位。在右移 n 位的时候,最右边的 n 位将被丢弃,但右移时处理最左边位情形有两种情况,如果数字是无符号数字,则用0填补最左边的 n 位;如果数字是一个有符号数值,则用数字的符号位填补最左边的 n 位。也就是说,如果数字原先是一个正数,则右移之后再最左边填补 n 个0;如果数字原先是负数,则右移之后在最左边补 n 个1。

负数的二进制表示(计算机用补码表示负数)
变成原码:将绝对值转换成二进制数,然后在最高位补1
变成反码:对原码除符号位外各位取反
变成补码:在反码最后一位加1

问题: 把整数右移一位和把整数除以2在数学上是等价的吗?
不是,除法的效率比一位运算效率低得多,在实际编程中应尽可能得用一位运算符代替乘除法。

值得注意的地方:
把一个整数减去1之后再后原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的1变成0。 很多二进制问题都可以用这种思路解决。


来自
《剑指Offer》
Coding-Interviews/二进制中1的个数.md at master · todorex/Coding-Interviews

相关文章:

  • mysql 5.7修改root登录密码
  • 关于 Double.compare()
  • mac关闭f11显示桌面快捷键
  • java中如何比较两个浮点型大小
  • 了解 BigDecimal.valueOf(double val)与new BigDecimal(double val) 的区别
  • 数值的整数次方 -- java
  • Could not get a resource from the pool 的原因之一
  • 打印从1到最大的n位数 -- java
  • 删除链表节点 -- java
  • npm 查看是否安装了某个包
  • 正则表达式匹配 -- java
  • 表示数值的字符串 -- java
  • 调整数组顺序使奇数位于偶数前面 -- java
  • 链表中倒数第K个节点 -- java
  • Mac查看npm安装位置
  • Java Agent 学习笔记
  • JS函数式编程 数组部分风格 ES6版
  • Laravel核心解读--Facades
  • react-native 安卓真机环境搭建
  • Redis在Web项目中的应用与实践
  • Selenium实战教程系列(二)---元素定位
  • 编写高质量JavaScript代码之并发
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 基于axios的vue插件,让http请求更简单
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 悄悄地说一个bug
  • 如何使用 JavaScript 解析 URL
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 算法---两个栈实现一个队列
  • 微服务入门【系列视频课程】
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • 进程与线程(三)——进程/线程间通信
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #android不同版本废弃api,新api。
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (多级缓存)多级缓存
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (七)c52学习之旅-中断
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (四) Graphivz 颜色选择
  • (四)Linux Shell编程——输入输出重定向
  • (算法)N皇后问题
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)SpringBoot3---尚硅谷总结
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .net framework 4.0中如何 输出 form 的name属性。
  • .Net mvc总结
  • .NET 服务 ServiceController