位1的个数,编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1‘ 的个数(也被称为汉明重量)。

news2024/11/13 10:19:47

题记:

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

提示:

请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 3 中,输入表示有符号整数 -3。

示例 1:

输入:n = 00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。

示例 2:

输入:n = 00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 ‘1’。

示例 3:

输入:n = 11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 ‘1’。

提示:

  • 输入必须是长度为 32 的 二进制串

进阶:

如果多次调用这个函数,你将如何优化你的算法?

题目来源:
作者:LeetCode
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xn1m0i/
来源:力扣(LeetCode)

解题方法:

java的18种写法,之前在公众号[数据结构和算法]中分为3个系列专门写过,这里就不在细写了,我把答案全部列出来,因为太多,我只给一些简单的提示,如果不懂的可以看下前面写的那3个系列,有图文分析
《364,位1的个数系列(一)》
《385,位1的个数系列(二)》
《402,位1的个数系列(三)》

或者也可以在下面留言,我来给你解答。

一:把n往右移32次,每次都和1进行与运算

public int hammingWeight(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if (((n >>> i) & 1) == 1) {
            count++;
        }
    }
    return count;
}

二:原理和上面一样,做了一点优化

public int hammingWeight(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if ((n & (1 << i)) != 0) {
            count++;
        }
    }
    return count;
}

转换为PHP代码为:

function hammingWeight($n) {
    $count = 0;
    while($n){
        $count += $n & 1;
        $n = $n >> 1;
    }
    return $count;
}

三:1每次往左移一位,再和n进行与运算

public int hammingWeight(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if ((n & (1 << i)) != 0) {
            count++;
        }
    }
    return count;
}

首先先来弄清楚位运算符:

位运算符

位运算符允许对整型数中指定的位进行求值和操作。

位移在 PHP
中是数学运算。向任何方向移出去的位都被丢弃。左移时右侧以零填充,符号位被移走意味着正负号不被保留。右移时左侧以符号位填充,意味着正负号被保留。

要用括号确保想要的优先级。例如 $a & b = = t r u e 先进行比较再进行按位与;而 ( b == true 先进行比较再进行按位与;而 ( b==true先进行比较再进行按位与;而(a & $b) == true
则先进行按位与再进行比较。

如果 &、 | 和 ^ 运算符的左右两个操作对象都是字符串,将对会组成字符串的字符 ASCII
值执行操作,结果也是一个字符串。除此之外,两个操作对象都将 转换为整数 ,结果也将会是整数。

如果 ~ 运算符的操作对象是字符串,则将对组成字符串的字符 ASCII 值进行操作, 结果将会是字符串,否则操作对象和结构都会是整数。

<< 和 >> 运算符的操作对象和结果始终都是整数。

弄清楚位运算符之后再来看一下方法一的原理:

我们知道在java语言中一个int类型有32个0或1组成。我们要计算有多少个1,这里主要以int型数据为例来分析。比如15在二进制中表示的是1111,有4个1,所以返回4。再比如16在二进制中表示的是10000,只有一个1,所以返回1。这题解法比较多,我们将会逐个分析。

通过移动数字计算

首先想到的是把要求的数字不停的往右移,然后再和1进行与运算,我们就以13为例画个图来分析下

在这里插入图片描述
看明白了上面的分析,代码就很容易多了,我们来看下代码

public int bitCount(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if (((n >>> i) & 1) == 1) {
            count++;
        }
    }
    return count;
}

上面的分析中我们看到,如果一个数往右移了几步之后结果为0了,就没必要在计算了,所以代码我们还可以在优化一点

public int bitCount(int n) {
    int count = 0;
    while (n != 0) {
        count += n & 1;
        n = n >>> 1;
    }
    return count;
}

方法二的原理:

上面我们使用的是把一个数字不断的往右移动,其实我们还可以保持原数字不变,用1和他进行与运算,然后通过移动1的位置来计算,这里我们判断的标准不是等于1,而是不等于0。我们还以13为例来画个图分析一下
在这里插入图片描述
这次我们移动的是1,我们来看一下代码

public int bitCount(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if ((n & (1 << i)) != 0) {
            count++;
        }
    }
    return count;
}

当然我们还可以通过运算的结果是否是1来判断也是可以的,我们只需要把往左移的1和n运算完之后再往右移即可,我们来看下代码

public int bitCount(int i) {
    int count = 0;
    for (int j = 0; j < 32; j++) {
        if ((i & (1 << j)) >>> j == 1)
            count++;
    }
    return count;
}

其他方法:

四:1每次往左移一位,把运算的结果在右移判断是否是1

public int hammingWeight(int i) {
    int count = 0;
    for (int j = 0; j < 32; j++) {
        if ((i & (1 << j)) >>> j == 1)
            count++;
    }
    return count;
}

五:这个是最常见的,每次消去最右边的1,直到消完为止

public int hammingWeight(int n) {
    int count = 0;
    while (n != 0) {
        n &= n - 1;
        count++;
    }
    return count;
}

六:把上面的改为递归

public int hammingWeight(int n) {
    return n == 0 ? 0 : 1 + hammingWeight(n & (n - 1));
}

七:查表

public int hammingWeight(int i) {
    //table是0到15转化为二进制时1的个数
    int table[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
    int count = 0;
    while (i != 0) {//通过每4位计算一次,求出包含1的个数
        count += table[i & 0xf];
        i >>>= 4;
    }
    return count;
}

八:每两位存储,使用加法(先运算再移位)

public int hammingWeight(int n) {
    n = ((n & 0xaaaaaaaa) >>> 1) + (n & 0x55555555);
    n = ((n & 0xcccccccc) >>> 2) + (n & 0x33333333);
    n = (((n & 0xf0f0f0f0) >>> 4) + (n & 0x0f0f0f0f));
    n = n + (n >>> 8);
    n = n +  (n >>> 16);
    return n & 63;
}

九:每两位存储,使用加法(先移位再运算)

public int hammingWeight(int n) {
    n = ((n >>> 1) & 0x55555555) + (n & 0x55555555);
    n = ((n >>> 2) & 0x33333333) + (n & 0x33333333);
    n = (((n >>> 4) & 0x0f0f0f0f) + (n & 0x0f0f0f0f));
    n = n + (n >>> 8);
    n = n + (n >>> 16);
    return n & 63;
}

十:和第8种思路差不多,只不过在最后几行计算的时候过滤的比较干净

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

十一:每4位存储,使用加法

public int hammingWeight(int n) {
    n = (n & 0x11111111) + ((n >>> 1) & 0x11111111) + ((n >>> 2) & 0x11111111) + ((n >>> 3) & 0x11111111);
    n = (((n & 0xf0f0f0f0) >>> 4) + (n & 0x0f0f0f0f));
    n = n + (n >>> 8);
    n = n + (n >>> 16);
    return n & 63;
}

十二:每3位存储,使用加法

public int hammingWeight(int n) {
    n = (n & 011111111111) + ((n >>> 1) & 011111111111) + ((n >>> 2) & 011111111111);
    n = ((n + (n >>> 3)) & 030707070707);
    n = ((n + (n >>> 6)) & 07700770077);
    n = ((n + (n >>> 12)) & 037700007777);
    return ((n + (n >>> 24))) & 63;
}

十三:每5位存储,使用加法

public int hammingWeight(int n) {
    n = (n & 0x42108421) + ((n >>> 1) & 0x42108421) + ((n >>> 2) & 0x42108421) + ((n >>> 3) & 0x42108421) + ((n >>> 4) & 0x42108421);
    n = ((n + (n >>> 5)) & 0xc1f07c1f);
    n = ((n + (n >>> 10) + (n >>> 20) + (n >>> 30)) & 63);
    return n;
}

十四:每两位存储,使用减法(先运算再移位)

public int hammingWeight(int i) {
    i = i - ((i >>> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
    i = (i + (i >>> 4)) & 0x0f0f0f0f;
    i = i + (i >>> 8);
    i = i + (i >>> 16);
    return i & 0x3f;
}

十五:每3位存储,使用减法

public int hammingWeight(int n) {
    n = n - ((n >>> 1) & 033333333333) - ((n >>> 2) & 011111111111);
    n = ((n + (n >>> 3)) & 030707070707);
    n = ((n + (n >>> 6)) & 07700770077);
    n = ((n + (n >>> 12)) & 037700007777);
    return ((n + (n >>> 24))) & 63;
}

十六:每4位存储,使用减法

public int hammingWeight(int n) {
    int tmp = n - ((n >>> 1) & 0x77777777) - ((n >>> 2) & 0x33333333) - ((n >>> 3) & 0x11111111);
    tmp = ((tmp + (tmp >>> 4)) & 0x0f0f0f0f);
    tmp = ((tmp + (tmp >>> 8)) & 0x00ff00ff);
    return ((tmp + (tmp >>> 16)) & 0x0000ffff) % 63;
}

十七:每5位存储,使用减法

public int hammingWeight(int n) {
    n = n - ((n >>> 1) & 0xdef7bdef) - ((n >>> 2) & 0xce739ce7) - ((n >>> 3) & 0xc6318c63) - ((n >>> 4) & 0x02108421);
    n = ((n + (n >>> 5)) & 0xc1f07c1f);
    n = ((n + (n >>> 10) + (n >>> 20) + (n >>> 30)) & 63);
    return n;
}

十八:每次消去最右边的1,可以参照第5种解法

public static int hammingWeight(int num) {
    int total = 0;
    while (num != 0) {
        num -= num & (-num);
        total++;
    }
    return total;
}

这题如果一直写下去,再写10种也没问题,如果上面的代码你都能看懂,你也会有和我一样的想法。但解这题的最终思路还是没变,所以再写下去也没有太大价值。上面有些写法其实也很鸡肋,这里只是告诉大家这样写也是可以实现的,虽然可能你永远都不这样去写。

方法来源:
作者:数据结构和算法
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xn1m0i/?discussion=BDVi4v
来源:力扣(LeetCode)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/802747.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL使用xtrabackup备份和恢复教程

1、xtrabackup说明 xtrabackup是percona开源的mysql物理备份工具。 xtrabackup 8.0支持mysql 8.0版本的备份和恢复。 xtrabackup 2.4支持mysql 5.7及以下版本的备份和恢复。 这里我以xtrabackup 8.0为例讲解备份和恢复的具体操作方法。 xtrabackup 2.4版本的使用上和8.0版本相…

PX4从放弃到精通(二十九):传感器冗余机制

文章目录 前言一、parametersUpdate二、imuPoll三、 put四、 confidence五、 get_best 前言 PX4 1.13.2 一个人可以走的更快&#xff0c;一群人才能走的更远&#xff0c;可加文章底部微信名片 代码的位置如下 PX4冗余机制主要通过传感读数错误计数和传感器的优先级进行选优 …

解决[Vue Router warn]: No match found for location with path “/day“问题

首先是升级vue-router4.0后会警告[Vue Router warn]: No match found for location with path "/day" 找了许久解决方案如下&#xff1a; 一、404页面不需要再异步路由后边添加&#xff0c;直接放到静态路由里即可 二、要注意不能写name&#xff0c;否则会刷新默认…

Parameter ‘roleList‘ not found.

Parameter roleList not found. Available parameters are [arg1, arg0, param1, param2] 多半是Mapper层传入多个参数的时候&#xff0c;没有加Param注解&#xff0c;导致BindException错误

ORA-01187 ORA-01110

ORA-01187: cannot read from file because it failed verification tests ORA-01110: data file 201: ‘/u01/app/oracle/oradata/CNDB/temp01.dbf’ 查询临时文件是存在的 重建临时数据文件 删除临时文件&#xff1a; alter database tempfile /u01/app/oracle/oradata…

56. 合并区间 排序

Problem: 56. 合并区间 文章目录 思路Code 思路 对数组排序&#xff0c;按照左端点从小到大排序。初始化Merged&#xff0c;将第一个区间放入。遍历intervals ,如果当前区间的左端点比merged最后一个区间的右端点大&#xff0c;不重合&#xff0c;直接将该区间加入最后&#xf…

《零基础入门学习Python》第070讲:GUI的终极选择:Tkinter7

上节课我们介绍了Text组件的Indexs 索引和 Marks 标记&#xff0c;它们主要是用于定位&#xff0c;Marks 可以看做是特殊的 Indexs&#xff0c;但是它们又不是完全相同的&#xff0c;比如在默认情况下&#xff0c;你在Marks指定的位置中插入数据&#xff0c;Marks 的位置会自动…

指针的基础应用(数组的颠倒和排序,二维数组的表示)

1.数组的颠倒&#xff1a;若有10个数字&#xff0c;那么数组的颠倒即 a[0]与a[9]交换,a[1]与a[8]交换&#xff0c;a[2]与a[7]交换&#xff0c;......a[4]与a[5]交换&#xff0c;所以到a[4]就颠倒完毕&#xff0c;即 (n-1)/2 若不用指针代码如下 #include<stdio.h>voi…

交互式AI技术与模型部署:使用Gradio完成一项简单的交互式界面

下面的这段代码使用Gradio库创建了一个简单的交互式界面。用户可以输入名称、选择是早上还是晚上、拖动滑动条来选择温度&#xff0c;然后点击"Launch"按钮&#xff0c;界面会显示相应的问候语和摄氏度温度。例如&#xff0c;如果用户输入"John"&#xff0…

iperf3 编译安装及网讯WX1860千兆网口测试

iperf3 编译安装及网讯1860千兆网口测试 编译安装 安装包下载地址:https://github.com/esnet/iperf/archive/refs/tags/3.8.tar.gz 将安装包iperf-3.8.tar.gz拷贝测试系统盘桌面,使用如下命令进行编译安装: tar zxvf iperf-3.8.tar.gz cd iperf-3.8 ./configure make s…

LeetCode-222-完全二叉树的节点个数

一&#xff1a;题目描述&#xff1a; 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节…

点餐系统测试报告

文章目录 一、项目介绍项目简介功能介绍 二、测试计划1 功能测试功能测试用例发现的 BUG 和 解决方法注册功能上传图片功能 2 自动化测试3 性能测试 一、项目介绍 项目简介 该项目是一个门店点餐系统&#xff0c;采用前后端分离的方式实现&#xff0c;后端框架是SSM&#xff…

R-并行计算

本文介绍在计算机多核上通过parallel包进行并行计算。 并行计算运算步骤&#xff1a; 加载并行计算包&#xff0c;如library(parallel)。创建几个“workers”,通常一个workers一个核&#xff08;core&#xff09;&#xff1b;这些workers什么都不知道&#xff0c;它们的全局环…

第一次后端复习整理(JVM、Redis、反射)

1. JVM 文章仅为自身笔记 详情查看一篇文章掌握整个JVM&#xff0c;JVM超详细解析&#xff01;&#xff01;&#xff01; 1.1 什么是JVM jvm是Java虚拟机 1.2 Java文件的编译过程 程序员编写代码形成.java文件经过javac编译成.class文件再通过JVM的类加载器进入运行时数据…

Java云电子病历源码:电子病历在线编辑

SaaS模式Java版云HIS系统的子系统云电子病历系统源码&#xff0c;本系统采用前后端分离模式开发和部署&#xff0c;支持电子病历四级。 电子病历系统主要为医院住院部提供医疗记录依据&#xff0c;协助医务人员在医疗活动过程中通过信息化手段生成的文字、图表、图形、数据、影…

华为数通HCIP-EVPN基础

MP-BGP MP-BGP&#xff08;Multiprotocol Extensions for BGP-4&#xff09;在RFC4760中被定义&#xff0c;用于实现BGP-4的扩展以允许BGP携带多种网络层协议&#xff08;例如IPv6、L3VPN、EVPN等&#xff09;。这种扩展有很好的后向兼容性&#xff0c;即一个支持MP-BGP的路由…

Java Swing Mysql实现的电影票订票管理系统

Java swing mysql实现的电影票订票管理系统&#xff0c;主要实现的功能有&#xff1a;用户端&#xff1a;登录注册、查看电影信息、选择影院场次、选座购票、查看自己的影票、评价电影等功能。管理员&#xff1a;登录、电影管理、影院管理、场次管理、影票管理等功能。 需要源…

echarts统计图x轴文字过长,以省略号显示,鼠标经过提示全部内容

效果图如下 主要代码如下&#xff1a; //1.js代码内加入extension方法&#xff0c;chart参数是echarts实例 function extension(chart) {// 注意这里&#xff0c;是以X轴显示内容过长为例&#xff0c;如果是y轴的话&#xff0c;需要把params.componentType xAxis改为yAxis/…

Shell脚本学习-read命令

Shell变量可以直接赋值或者脚本传参的方式&#xff0c;还可以使用echo命令从标准输入中获得&#xff0c;read为bash内置命令。 [rootvm1 ~]# type echo echo is a shell builtin常用参数&#xff1a; -p prompt&#xff1a;设置提示信息&#xff0c;我们看help内容的信息&…

学习笔记|百度文心千帆大模型平台测试及页面交互简易代码

目前百度文心一言的内测资格申请相当拉胯&#xff0c;提交申请快3个月&#xff0c;无任何音讯。不知道要等到什么时候。 百度适时开放了百度文心千帆大模型平台&#xff0c;目前可以提交申请测试&#xff0c;貌似通过的很快&#xff0c;已取得测试申请资格&#xff0c;可以用起…