首页/新闻资讯/正文详情

Hot 100 --- 只出现一次的数字

发布时间:2026/9/27 4:03:40 来源:云帆数科 栏目:资讯中心
Hot 100 --- 只出现一次的数字
本文概览本文讲解只出现一次的数字其余数字都出现两次异或运算满足 aa0、a0a 且可交换可结合把所有数字全异或一遍成对的互相抵消成 0剩下的就是答案。用二进制逐位演示抵消过程O(n) 时间、O(1) 空间一、题目二、题目分析1. 题目要求给你一个非空整数数组nums除了某个元素只出现一次以外其余每个元素均出现两次。找出那个只出现了一次的元素。进阶要求你的算法应该具有线性时间复杂度。你可以不使用额外空间来实现吗示例 1nums [2, 2, 1]→ 1示例 2nums [4, 1, 2, 1, 2]→ 4示例 3nums [1]→ 12. 怎么想这题题目给出的条件里有个关键信息除了答案其他数字都是成对出现的。那最直观的思路就来了——怎么把成对的数字消掉、只留下那个落单的顺着这个想法有几条路可以走用哈希集合把出现过的数字记下来第一次遇到就放进去第二次遇到就说明它成对了从集合里删掉。最后集合里剩下的就是那个落单的。这条路好想但要多花 O(n) 的空间。排序之后两两比较成对的会挨在一起扫一遍就能找出落单的。这是 O(n log n)也没达到线性的要求。有没有一种运算天生就能让两个相同的数互相抵消有就是异或。它比前两条路都好因为既快又不需要额外空间。3. 需要解决哪几个问题问题一哈希集合和排序这两条路为什么达不到题目线性 不用额外空间的要求问题二核心异或为什么能让相同的数字互相抵消从二进制位上到底发生了什么问题三为什么把所有数字一股脑异或起来完全不管顺序也能得出正确答案三、方法一哈希集合O(n) 空间1. 思路概览publicintsingleNumber(int[]nums){SetIntegersetnewHashSet();for(intnum:nums){if(!set.add(num)){// add 返回 false 说明这个数已经在集合里了是对里的第二个set.remove(num);}}returnset.iterator().next();}思路简要说明进进出出第一次遇到某个数就放进去第二次遇到add返回false说明它成对了从集合里移走剩下的就是答案所有成对的都被移走了集合里只剩那个落单的时间复杂度 O(n)空间 O(n)不满足进阶要求用了 O(n) 的额外空间2. 思路详解这个思路就是拿集合模拟配对的过程。set.add(num)会返回一个布尔值放进去之前集合里没有这个数就返回true已经有了就返回false。所以第一次遇到4集合里没有 →add返回true→ 留着第二次遇到4集合里已经有了 →add返回false→ 说明这一对凑齐了两个一起消掉把4从集合里remove。以[4, 1, 2, 1, 2]为例遇到 4set [4] 遇到 1set [4, 1] 遇到 2set [4, 1, 2] 遇到 11 已存在 → set [4, 2] 遇到 22 已存在 → set [4] 返回 4 ✓逻辑很直白代价是那个集合占用了 O(n) 的空间——题目偏偏要求不使用额外空间。3. 复杂度分析时间复杂度 O(n)遍历一次哈希操作均摊 O(1)。空间复杂度 O(n)最坏情况下集合里存近 n 个数。四、方法二排序后两两比较O(n log n)1. 思路概览publicintsingleNumber(int[]nums){Arrays.sort(nums);for(inti0;i1nums.length;i2){if(nums[i]!nums[i1]){returnnums[i];}}returnnums[nums.length-1];}思路简要说明排序让成对的数字挨在一起排完之后相同的数一定相邻两两跳着扫每次看一对(nums[i], nums[i1])不相等说明nums[i]就是落单的扫完没找到说明落单的是最后一个元素时间复杂度 O(n log n)空间 O(1)不算排序本身的开销2. 思路详解排序会把相等的元素排到一起所以数组变成一对、一对……最后可能单一个的样子。于是从下标 0 开始每次跨两步看一对如果这一对相等说明这对配上了往后跳两步继续如果这一对不相等说明前一个数没有同伴——它就是答案。用[4, 1, 2, 1, 2]举例排序后是[1, 1, 2, 2, 4]i0nums[0]1 和 nums[1]1 相等 → 跳过 i2nums[2]2 和 nums[3]2 相等 → 跳过 i4i1 越界循环结束 → 返回最后一个 4 ✓这个方法空间省了但排序要 O(n log n)比线性的要求慢一截。3. 复杂度分析时间复杂度 O(n log n)排序占主要开销。空间复杂度 O(1)只用了下标变量。五、方法三异或O(n) 时间 O(1) 空间1. 思路概览publicintsingleNumber(int[]nums){intans0;for(intnum:nums){ans^num;}returnans;}思路简要说明一个变量一路异或到底ans从 0 开始把每个数都异或进去成对的自动抵消两个相同的数异或得 0等于没参与剩下的就是答案所有成对数字抵消完ans里留下的只有那个落单的时间复杂度 O(n)空间 O(1)2. 思路详解第一步解决为什么异或能抵消——先看异或在二进制位上的规则异或^是按位运算先把两个数都写成二进制再让它们一位对齐一位地算。因为是二进制每一位上只可能是 0 或 1 两种值两个位碰在一起一共也只有四种组合规则就两条相同得 00 ^ 0 0 1 ^ 1 0 不同得 10 ^ 1 1 1 ^ 0 1这里要特别注意上面式子里的 0 和 1 全都是二进制位bit上的值说的是这一位取 0 还是取 1不是十进制的数字 0 和 1。所以这四行的意思是把某一位上的两个 bit 做异或得到的结果 bit是 0 还是 1——两个 bit 相同结果 bit 就是 0两个 bit 不同结果 bit 就是 1。一句话记住“相同得 0不同得 1”。由此立刻能推出两个性质a ^ a 0 ← 两个一模一样的数每一位上的两个 bit 都相同逐位算出来都是 bit 0一位一位全是 0整个数就是 0 a ^ 0 a ← 每一位拿 bit 和 0 去比原来是 bit 1 的不同得 1原来是 bit 0 的相同得 0结果原样不动第一个性质正是我们想要的两个相同的数异或结果就是 0等于互相抵消没出现过。第二步把示例 2 拆成二进制看抵消过程拿nums [4, 1, 2, 1, 2]来先把每个数写成二进制4 1 0 0 1 0 0 1 2 0 1 0 1 0 0 1 2 0 1 0现在一位一列地竖着看每一位各自做异或位2 位1 位0 4 1 0 0 1 0 0 1 2 0 1 0 1 0 0 1 2 0 1 0 ------------------------ 结果 1 0 0 4逐位解释位 0这一列是0、1、0、1、0。两个1来自那两个1异或时1 ^ 1 0正好抵消最后剩 0。位 1这一列是0、0、1、0、1。两个1来自那两个2同样抵消剩 0。位 2这一列是1、0、0、0、0。只有4贡献了一个1没有谁能和它抵消于是留下 1。三位合起来1 0 0正是 4——那个落单的数。换一个角度把整个异或过程一步步算出来ans 初始 000 ans ^ 4 000 ^ 100 100 → 4 ans ^ 1 100 ^ 001 101 → 5 ans ^ 2 101 ^ 010 111 → 7 ans ^ 1 111 ^ 001 110 → 6 ans ^ 2 110 ^ 010 100 → 4 ✓中间几步的ans是 5、7、6看着毫无规律但那只是还没配上对的临时状态。等到把1和1、2和2都异或进去它们两两抵消最后只剩 4。这也说明一件事不需要关心中间过程是什么只要保证每个数字都被异或了一次成对的就会自己消掉。第三步解决为什么可以不管顺序异或满足交换律a ^ b b ^ a和结合律(a ^ b) ^ c a ^ (b ^ c)。原因从按位独立就能看出来异或的每一位各算各的不同位之间互不影响。而单独看某一位这一位上无非是一堆 0 和 11的个数是偶数就全抵消、是奇数就留一个 1——数一数就行跟谁先谁后毫无关系。所以整个数组可以看成所有数字一起异或怎么打乱顺序、怎么分组都行4 ^ 1 ^ 2 ^ 1 ^ 2 (1 ^ 1) ^ (2 ^ 2) ^ 4 ← 用交换律结合律把成对的挪到一起 0 ^ 0 ^ 4 4成对的都变成了 00 ^ 4 4a ^ 0 a答案就浮出来了。第四步代码细节intans0;// 从 0 开始因为 0 异或任何数都是那个数本身0 ^ x xfor(intnum:nums){ans^num;// 逐个异或进去}returnans;为什么初值是 00 ^ x x0 是异或运算的零元拿它起步不会影响结果。数组只有一个元素循环走一遍ans 0 ^ nums[0] nums[0]直接返回它自己符合预期。负数也没问题异或是补码上按位算的性质a ^ a 0、a ^ 0 a对负数一样成立。3. 复杂度分析时间复杂度 O(n)一次遍历每个数只做一次异或。空间复杂度 O(1)只用一个变量ans。六、总结方法时间空间是否满足进阶要求哈希集合O(n)O(n)否排序 两两比较O(n log n)O(1)否时间不够线性异或O(n)O(1)是这题的关键在于抓住其余元素都出现两次这个条件然后找到一种相同的两个数碰一起就消失的运算——异或正好就是a ^ a 0成对的自动抵消a ^ 0 a落单的不受影响可交换、可结合所以能无视顺序从头到尾一把梭。前两种方法都能算出答案但一个要多花空间、一个要多花时间异或同时把时间和空间都做到了最优而且代码只有三行。

相关推荐

02-技术教程-CIMPro孪大师8.0实战5个AI辅助零代码开发高效方法
02-技术教程-CIMPro孪大师8.0实战5个AI辅助零代码开发高效方法

CIMPro孪大师8.0实战指南:AI辅助零代码开发让效率提升10倍的5个核心方法 摘要: CIMPro孪大师8.0版本重磅发布,AI辅助零代码开发能力大幅增强。本文通过5个实战案例,详细解析如何利用CIMPro 8.0的AI功能,从传统开发模式… · 2026/9/27 4:03:34

卫浴毛巾架网站建设避坑:图解步骤拆解3种技术栈成本
卫浴毛巾架网站建设避坑:图解步骤拆解3种技术栈成本

卫浴毛巾架网站建设避坑:图解步骤拆解3种技术栈成本 找卫浴毛巾架建站公司,最怕的就是报价虚高,三千块的项目敢报你一万五。很多老板觉得网站就是个展示橱窗,其实里面水很深,选错技术栈,后期维护费能把你吃穷。今天把 图解步骤… · 2026/9/27 4:03:34

3招搞定mooc网站建设新手入门避坑指南
3招搞定mooc网站建设新手入门避坑指南

3招搞定mooc网站建设新手入门避坑指南 找建站公司怕被坑高价?这绝对是很多新手入门时的第一道坎。我见过太多人花了几万块,最后发现网站连基本的移动端适配都没做好,更别提SEO了。其实,对于mooc网站建设这种特定场景,核心不在于堆砌多少功能… · 2026/9/27 4:03:28

treg金融数据工具:Coingecko、Tiingo、Polygon行情API按次调用教程
treg金融数据工具:Coingecko、Tiingo、Polygon行情API按次调用教程

treg金融数据工具:Coingecko、Tiingo、Polygon行情API按次调用教程 【免费下载链接】treg OpenRouter for agent tools. Join community here: https://discord.gg/6mQYYfFMAn 项目地址: https://gitcode.com/GitHub_Trending/treg/treg treg 是一个面向 Age… · 2026/9/27 4:43:34

STM32+C++11裸机开发:用constexpr和noexcept夺回代码主权
STM32+C++11裸机开发:用constexpr和noexcept夺回代码主权

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 4:43:34

保距变换概念让5000年都无人能识的“更无理”标准自然数一下子浮出水面推翻百年集论
保距变换概念让5000年都无人能识的“更无理”标准自然数一下子浮出水面推翻百年集论

保距变换概念让5000年都无人能识的“更无理”标准自然数一下子浮出水面推翻百年集论黄小宁中学生就应熟悉非常简单易懂的保距变换概念。不是千载而是五千载难逢的太重大数学发现来自于太浅显的保距变换概念。本文的论据是:保距变换概念表明点集j失去部分元点变为其非… · 2026/9/27 4:43:34

深圳建设企业网站避坑指南:3种方案费用拆解与最佳实践
深圳建设企业网站避坑指南:3种方案费用拆解与最佳实践

深圳建设企业网站避坑指南:3种方案费用拆解与最佳实践 网站被黑挂马,后台突然多了个博彩广告,客户点进来全是弹窗,这种 nightmare… · 2026/9/27 4:43:27

高并发流量治理实战(5):热点 Key 探测与多级缓存:突发流量承接方案
高并发流量治理实战(5):热点 Key 探测与多级缓存:突发流量承接方案

从"面状流量"到"点状流量" 前四篇治理的都是"面状"压力:总量超预期,靠限流分层、熔断止损、降级舍车。但有一类事故长得不一样——总 QPS 没超任何阈值,所有压力却集中在同一个键上。场景:内容平台… · 2026/9/27 4:43:27

解决Calibre LVS中标准单元bulk连接缺失:v2lvs转换与TCL脚本修复实战
解决Calibre LVS中标准单元bulk连接缺失:v2lvs转换与TCL脚本修复实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 4:43:27

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码