【leetcode热题】 位1的个数

news2024/11/18 16:41:59

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

提示:

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

示例 1:

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

示例 2:

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

示例 3:

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

解法一

简单粗暴些,依次判断最低位是否是 1,然后把它加入到结果中。判断最低位是否是 1,我们只需要把原数字和 000000..001 相与,也就是和 1 相与即可。

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

解法二

比较 trick 的方法,官方 题解提供的,分享一下。

有一个方法,可以把最右边的 1 置为 0,举个具体的例子。

比如十进制的 10,二进制形式是 1010,然后我们只需要把它和 9 进行按位与操作,也就是 10 & 9 = (1010) & (1001) = 1000,也就是把 1010 最右边的 1 置为 0

规律就是对于任意一个数 n,然后 n & (n-1) 的结果就是把 n 的最右边的 1 置为 0 。

也比较好理解,当我们对一个数减 1 的话,比如原来的数是 ...1010000,然后减一就会向前借位,直到遇到最右边的第一个 1,变成 ...1001111,然后我们把它和原数按位与,就会把从原数最右边 1 开始的位置全部置零了 ...10000000

有了这个技巧,我们只需要把原数依次将最右边的 1 置为 0,直到原数变成 0,记录总共操作了几次即可。

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

解法三

有点类似于 190 题 的解法二,通过整体的位操作解决问题,参考 这里-by-time-m-is-the-count-of-1's-and-another-several-method-of-O(1)-time) ,也是比较 trick 的,不容易想到,但还是很有意思的。

本质思想就是用本身的比特位去记录对应位数的比特位 1 的个数,举个具体的例子吧。为了简洁,求一下 8 比特的数字中 1 的个数。

统计数代表对应括号内 1 的个数
1   1   0   1   0   0   1   1
首先把它看做 8 组,统计每组 1 的个数
原数字:(1)   (1)   (0)   (1)   (0)   (0)   (1)   (1)
统计数:(1)   (1)   (0)   (1)   (0)   (0)   (1)   (1)
每个数字本身,就天然的代表了当前组 1 的个数。

接下来看做 4 组,相邻两组进行合并,统计数其实就是上边相邻组统计数相加即可。
原数字:(1    1)   (0    1)   (0   0)   (1  1)
统计数:(1    0)   (0    1)   (0   0)   (1  0)
十进制:   2           1         0         2        

接下来看做 2 组,相邻两组进行合并,统计数变成上边相邻组统计数的和。
原数字:(1    1     0    1)   (0   0     1  1)
统计数:(0    0     1    1)   (0   0     1  0)
十进制:         3                   2  

接下来看做 1 组,相邻两组进行合并,统计数变成上边相邻组统计数的和。
原数字:(1    1     0    1     0   0     1  1)
统计数:(0    0     0    0     0   1     0  1)
十进制:                   5

看一下 「统计数」的变化,也就是统计的 1 的个数。

看下二进制形式的变化,两两相加。

看下十进制形式的变化,两两相加。

最后我们就的得到了 1 的个数是 5

所以问题的关键就是怎么实现每次合并相邻统计数,我们可以通过位操作实现,举个例子。

比如上边 4 组到 2 组中的前两组合成一组的变化。要把 (1 0) (0 1) 两组相加,变成 (0 0 1 1) 。其实我们只需要把 1001 和 0011 相与得到低两位,然后把 1001 右移两位再和 0011 相与得到高两位,最后将两数相加即可。也就是(1001) & (0011) + (1001) >>> 2 & (0011)= 0011

扩展到任意情况,两组合并成一组,如果合并前每组的个数是 n,合并前的数字是 x,那么合并后的数字就是 x & (000...111...) + x >>> n & (000...111...),其中 0 和 1 的个数是 n

public int hammingWeight(int n) {
    n = (n & 0x55555555) + ((n >>> 1) & 0x55555555); // 32 组向 16 组合并,合并前每组 1 个数
    n = (n & 0x33333333) + ((n >>> 2) & 0x33333333); // 16 组向 8 组合并,合并前每组 2 个数
    n = (n & 0x0f0f0f0f) + ((n >>> 4) & 0x0f0f0f0f); // 8 组向 4 组合并,合并前每组 4 个数
    n = (n & 0x00ff00ff)+ ((n >>> 8) & 0x00ff00ff); // 4 组向 2 组合并,合并前每组 8 个数
    n = (n & 0x0000ffff) + ((n >>> 16) & 0x0000ffff); // 2 组向 1 组合并,合并前每组 16 个数
    return n;
}

写成 16 进制可能不好理解,我们拿16 组向 8 组合并举例,合并前每组 2 个数。也就是上边我们推导的,我们要把 (1 0) (0 1) 两组合并,需要和 0011 按位与,写成 16 进制就是 3,因为合并完是 8 组,所以就是 8 个 3,即 0x33333333

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

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

相关文章

2024.03.23 健身打卡第 34 天

君之英才,实乃盖世无双,渴求统一大业却属鲲鹏之志。然涓滴之水汇成江河,已属不易,奔流向前,汇入大海之时,更会倍感自身之渺茫。 2024.03.23 健身打卡第 34 天

架构整洁之道-读书总结

1 概述 1.1 关于本书 《架构整洁之道》(Clean Architecture: A Craftsman’s Guide to Software Structure and Design)是由著名的软件工程师Robert C. Martin(又称为Uncle Bob)所著。这本书提供了软件开发和架构设计的指导原则…

王道C语言督学营OJ课后习题(课时14)

#include <stdio.h> #include <stdlib.h>typedef char BiElemType; typedef struct BiTNode{BiElemType c;//c 就是书籍上的 datastruct BiTNode *lchild;struct BiTNode *rchild; }BiTNode,*BiTree;//tag 结构体是辅助队列使用的 typedef struct tag{BiTree p;//树…

文件包含一-WEB攻防-PHP应用文件包含LFIRFI伪协议编码算法无文件利用黑白盒

演示案例&#xff1a; 文件包含-原理&分类&利用&修复黑盒利用-VULWEB-有无包含文件白盒利用-CTFSHOW-伪协议玩法 #文件包含-原理&分类&利用&修复 1、原理 程序开发人员通常会把可重复使用的函数写到单个文件中&#xff0c;在使用某些函数时&#xff0c…

MySQL---视图

目录 一、介绍 二、语法 三、视图的更新 四、视图作用 一、介绍 视图&#xff08;View&#xff09;是一种虚拟存在的表。视图中的数据并不在数据库中实际存在&#xff0c;行和列数据来自定义视图的查询中使用的表&#xff0c;并且是在使用视图时动态生成的。 通俗的讲&#…

CSS时钟案例

文章目录 1. 演示效果2. 分析思路3. 代码实现 1. 演示效果 2. 分析思路 背景是表盘&#xff0c;不用自己制作然后用CSS的定位做时针&#xff0c;分针和秒针黑点用伪元素::after生成转动用animation实现 3. 代码实现 <!DOCTYPE html> <html lang"en">&…

密码学之哈希碰撞和生日悖论

哈希碰撞 哈希碰撞是指找到两个不一样的值&#xff0c;它们的哈希值却相同 假设哈希函数的取值空间大小为k &#xff0c;计算次数为n 先算每个值不一样的概率P’ 所以至少两个值相同(即存在哈希碰撞)的概率P为 生日悖论 假设班里有50个人&#xff0c;求班里至少两个人相同…

java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics

今天在使用springBoot连接influxdb报错 java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics 详细报错如下&#xff0c;提出我们缺少一个依赖 原因是由于创建influxdb客户端缺少Kotlin运行时库 解决办法就是 1.显示的添加okhttp的依赖 <dependency>…

如何用VSCode和Clangd与Clang-Format插件高效阅读Linux内核源码及写驱动

一、如何高效阅读Linux源码&#xff1a;基于clangd uboot/busybox等都可以用这种方式&#xff0c;理论上说所有基于Make和Cmake的源码工程都可以用这套方案 阅读Linux源码最大问题在于调用链太复杂&#xff0c;一个函数或变量引用太多&#xff0c;source insight和cscope等基于…

Uibot6.0 (RPA财务机器人师资培训第1天 )RPA+AI、RPA基础语法

训练网站&#xff1a;泓江科技 (lessonplan.cn)https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981(本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff09; 紧接着小北之前的几篇博客&#xff0c;友友们我们即将开展新课的学习~…

Nacos部署(三)Docker部署Nacos2.3单机环境

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; Nacos部署&#xff08;三&#xff09;Docker部署Nacos2.3单机环境 ⏱️…

Python数据结构实验 队列的实现

一、实验目的 1&#xff0e;掌握用Python定义队列的顺序存储结构和链式存储结构&#xff0c;以便在实际背景下灵活运用&#xff1b; 2&#xff0e;掌握队列的特点&#xff0c;即先进先出的原则&#xff1b; 3&#xff0e;掌握队列的基本操作实现方法。 二、实验环境 1&…

BufferedInputStream详解

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java之IO流啦&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好习惯&am…

javase day10笔记

第十天课堂笔记 debug调试★★★ 步骤: 设置断点 - > 启动调试debug -> 单步运行 -> 观察参数 单步跳过f8: 向下执行语句,不进入方法内部单步跳入f7: 进入方法内部执行单步跳出shift f8: 跳出当前方法,到方法调用处跳转到光标所在的位置alt f9: 变量整合 变量 …

【力扣hot100】1. 两数之和 49.字母异位词分组 128. 最长连续序列

目录 1. 两数之和题目描述做题思路参考代码 49.字母异位词分组题目描述做题思路参考代码 128. 最长连续序列题目描述做题思路参考代码 1. 两数之和 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数…

亚马逊云科技《生成式 AI 精英速成计划》

最近亚马逊云科技推出了「生成式AI精英速成计划」&#xff0c;获取包含&#xff1a;免费学习热门生成式AI课程、技能证书、人力主管的面试辅导、云计算国际认证、免费去往北美参加全球用户大会等&#xff5e; 针对开发者和企业非技术专业人士&#xff0c;了解如何使用大模型平台…

【机器学习之---统计】统计学基础概念

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 统计学基础 1. 频率派 频率学派&#xff08;传统学派&#xff09;认为样本信息来自总体&#xff0c;通过对样本信息的研究可以合理地推断和估计总体信息…

怎么拆解台式电脑风扇CPU风扇的拆卸步骤-怎么挑

今天我就跟大家分享一下如何选购电脑风扇的知识。 我也会解释一下机箱散热风扇一般用多少转。 如果它恰好解决了您现在面临的问题&#xff0c;请不要忘记关注本站并立即开始&#xff01; 文章目录列表&#xff1a;大家一般机箱散热风扇都用多少转&#xff1f; 机箱散热风扇选择…

PieCloudDB Database 3.0 正式发布丨数仓虚拟化流转数据要素

3月14日&#xff0c;拓数派 2024 年度战略暨新产品发布会在上海国际会议中心成功举行。本次大会的主题为「数仓虚拟化 流转数据要素」&#xff0c;吸引了众多业内资深专家和合作伙伴参与&#xff0c;共同探讨数据要素流转和数字技术创新等热门话题。 拓数派创始人兼 CEO 冯雷&…

40 openlayers setCenter 之后 绘制了Overlay 地图定位异常

前言 这是之前在 生产环境碰到的一个问题 这个其实就是 业务上一个地图点击点位展示详情, 然后再点击另外一个点位 展示详情, 切换中心店的这个过程 其主要的问题是 使用 openlayers 的 Map.View.setCenter() 了之后, 整个地图的中心点切换到了一个莫名其妙的地方 然后 经…