2026/4/15 10:49:54
网站建设
项目流程
网站信息化建设报送,优化网站入口页面的四个维度,网页数据库系统怎么做,网站排名优化外包Java版LeetCode热题100之只出现一次的数字#xff1a;从暴力破解到异或优化#xff0c;深入理解位运算在算法中的妙用 引言
在算法面试中#xff0c;“只出现一次的数字”是一道经典且高频的题目#xff0c;它不仅考察了候选人对基本数据结构的理解#xff0c;更深入地测…Java版LeetCode热题100之只出现一次的数字从暴力破解到异或优化深入理解位运算在算法中的妙用引言在算法面试中“只出现一次的数字”是一道经典且高频的题目它不仅考察了候选人对基本数据结构的理解更深入地测试了其对位运算这一底层编程技巧的掌握程度。本题出自 LeetCode 热题 100被众多大厂如 Google、Amazon、字节跳动等反复使用是面试准备中不可绕过的一环。本文将围绕这道题展开全方位、多维度、深层次的剖析。我们将从最朴素的解法出发逐步过渡到最优解并在此过程中穿插数据结构回顾、时间/空间复杂度分析、面试官可能提出的问题、实际开发中的应用场景等内容力求帮助读者不仅“会做这道题”更能“理解这类问题”并具备举一反三的能力。全文结构如下原题回顾明确问题定义与约束条件原题分析拆解题干关键信息答案构思从暴力到优化的思维演进完整答案提供可运行的 Java 代码代码分析逐行解读核心逻辑复杂度分析时间与空间效率评估问题解答常见疑问与误区澄清优化思路为何异或是最优解基础知识点回顾哈希表、集合、位运算详解面试官提问环节模拟真实面试场景实际开发应用这道题真的只是“玩具”吗相关题目推荐拓展训练清单总结与延伸升华认知构建知识体系一、原题回顾题目给你一个非空整数数组nums除了某个元素只出现一次以外其余每个元素均出现两次。找出那个只出现了一次的元素。要求设计并实现线性时间复杂度的算法该算法只使用常量额外空间即 O(1) 空间。示例示例 1 输入nums [2,2,1] 输出1 示例 2 输入nums [4,1,2,1,2] 输出4 示例 3 输入nums [1] 输出1约束条件1 nums.length 3 * 10^4-3 * 10^4 nums[i] 3 * 10^4除一个元素外其余元素均出现两次二、原题分析这道题的关键在于理解题目的隐含条件和硬性约束唯一性只有一个数字出现一次其余都出现恰好两次。这意味着不存在“出现三次”或“多个唯一值”的情况。线性时间O(n) 时间复杂度排除了排序O(n log n)等方案。常量空间O(1) 额外空间意味着不能使用哈希表、集合等需要 O(n) 空间的结构。整数范围包含负数说明不能仅依赖正整数特性。这些限制条件直接排除了大多数直观解法迫使我们思考更“聪明”的方法——位运算。三、答案构思从暴力到最优的思维演进面对一个问题优秀的工程师不会直接跳到最优解而是先尝试可行方案再逐步优化。下面我们按思维路径递进思路一暴力双重循环不推荐遍历每个元素再内层遍历统计其出现次数。时间复杂度O(n²)空间复杂度O(1)缺点效率极低无法通过大测试用例。思路二使用 HashSet集合遍历数组若元素不在集合中则加入若已在则移除。最终集合中只剩一个元素即为答案。SetIntegersetnewHashSet();for(intnum:nums){if(set.contains(num)){set.remove(num);}else{set.add(num);}}returnset.iterator().next();时间复杂度O(n)空间复杂度O(n)优点逻辑清晰缺点违反“常量空间”要求思路三使用 HashMap哈希表统计每个数字的出现频率最后遍历 map 找出 value 为 1 的 key。MapInteger,IntegermapnewHashMap();for(intnum:nums){map.put(num,map.getOrDefault(num,0)1);}for(Map.EntryInteger,Integerentry:map.entrySet()){if(entry.getValue()1)returnentry.getKey();}时间复杂度O(n)空间复杂度O(n)缺点同样不满足空间限制思路四数学法求和差值利用集合去重sum(set) * 2 - sum(nums) 唯一元素例如[4,1,2,1,2]→ set {1,2,4} → sum(set)7 → 7*214 → sum(nums)10 → 14-104SetIntegersetnewHashSet();inttotal0,uniqueSum0;for(intnum:nums){totalnum;set.add(num);}for(intnum:set)uniqueSumnum;returnuniqueSum*2-total;时间复杂度O(n)空间复杂度O(n)缺点仍需额外空间且存在整数溢出风险虽然本题范围小思路五位运算 —— 异或XOR【最优解】这是本题的标准答案也是面试官期待看到的解法。核心思想利用异或运算的三大性质a ^ 0 aa ^ a 0异或满足交换律和结合律由于数组中除一个数外其余都成对出现那么所有成对的数异或后为 0最终结果就是那个唯一的数。例如[4,1,2,1,2]计算过程4 ^ 1 ^ 2 ^ 1 ^ 2 4 ^ (1^1) ^ (2^2) 4 ^ 0 ^ 0 4四、完整答案Java 实现classSolution{publicintsingleNumber(int[]nums){intresult0;for(intnum:nums){result^num;}returnresult;}}✅ 该代码满足时间复杂度 O(n)空间复杂度 O(1)代码简洁、高效、无副作用五、代码分析让我们逐行解析这段看似简单的代码intresult0;初始化结果为 0。根据异或性质a ^ 0 a0 是异或运算的“单位元”。for(intnum:nums){result^num;}遍历数组中的每一个元素将其与result进行异或。由于异或满足交换律和结合律顺序无关紧要。成对出现的数字会相互抵消a ^ a 0最终只剩下唯一出现一次的数字。returnresult;返回最终结果。关键洞察整个过程不需要记录任何中间状态仅用一个变量即可完成计算完美契合 O(1) 空间要求。六、时间复杂度与空间复杂度分析时间复杂度O(n)只需遍历数组一次执行 n 次异或操作。异或操作是 CPU 原生指令时间复杂度为 O(1)。总体O(n)空间复杂度O(1)仅使用了一个额外的整型变量result。不依赖输入规模空间恒定。总体O(1) 对比其他方法方法时间复杂度空间复杂度是否满足要求双重循环O(n²)O(1)❌ 时间超限HashSetO(n)O(n)❌ 空间超限HashMapO(n)O(n)❌ 空间超限数学求和O(n)O(n)❌ 空间超限异或O(n)O(1)✅ 完全满足七、问题解答常见疑问与误区Q1为什么异或能解决这个问题答因为题目保证“其余元素均出现两次”而a ^ a 0所以所有成对元素异或后消失只剩唯一元素。Q2如果数组中有负数异或还有效吗答完全有效异或运算是按位操作与数值正负无关。Java 中int是 32 位有符号整数异或直接作用于二进制表示。Q3能否用加减法代替异或比如a -a 0答理论上可以但存在两大问题溢出风险大数相加可能溢出虽然本题范围小但不通用无法区分顺序加减不具备“自反抵消”的确定性如a b - a b但需知道何时加何时减而异或天然具备“自反性”和“无状态性”。Q4如果唯一元素出现奇数次如3次其余出现偶数次还能用异或吗答不能直接使用。此时异或结果为a ^ a ^ a a看似可行但若其他元素出现4次、6次等仍可抵消。但题目明确限定“其余出现两次”所以无需考虑。⚠️ 注意若题目变为“其余出现三次”则需用更复杂的位计数方法如模3计数不属于本题范畴。八、优化思路为何异或是最优解从信息论角度看我们需要从 n 个数中提取 1 个“异常”信息。异或操作本质上是在进行无损压缩将成对信息压缩为 0保留差异信息。它利用了题目给出的强约束条件其余元素恰好出现两次实现了“零存储”的状态跟踪。从工程实践看异或操作是 CPU 最快的位运算之一通常只需 1 个时钟周期。无内存分配无 GC 压力适合高并发、低延迟场景。因此异或不仅是理论最优也是实践最优。九、数据结构与算法基础知识点回顾1. 哈希表HashMap原理基于哈希函数将 key 映射到桶bucket支持 O(1) 平均查找。适用场景快速查找、去重、计数。本题局限需要 O(n) 空间。2. 集合HashSet本质基于 HashMap 实现只存储 key。特点元素唯一、无序。本题用途去重或配对消除。3. 位运算Bitwise Operations异或XOR,^相同为 0不同为 1性质a ^ 0 aa ^ a 0交换律、结合律典型应用交换两个数无需临时变量找唯一数加密一次性密码本其他位运算与掩码操作或|设置位非~取反左移、右移快速乘除 2建议熟练掌握位运算是进阶算法工程师的必备技能。十、面试官提问环节模拟真实面试Q1你能解释一下为什么异或能满足常量空间吗期望回答因为异或操作具有“自反性”和“结合律”我们不需要存储任何中间状态只需一个累加变量即可完成全部计算空间不随输入规模增长。Q2如果题目改为“有两个数字只出现一次其余出现两次”如何解决期望回答先对所有数异或得到a ^ b设两个唯一数为 a, b找到a ^ b中任意一个为 1 的位说明 a 和 b 在该位不同按该位将数组分为两组每组分别异或即可得到 a 和 b时间 O(n)空间 O(1)Q3异或操作在底层是如何实现的加分回答在 CPU 中异或由 ALU算术逻辑单元直接支持通常通过 XOR 门电路实现速度极快常用于校验、加密、图形处理等领域。Q4这个解法能扩展到浮点数吗回答不能。浮点数的二进制表示包含符号位、指数位、尾数位直接异或无意义。且浮点数比较应避免直接用。本题限定为整数。十一、这道算法题在实际开发中的应用很多人认为 LeetCode 题是“玩具”但其实位运算在工业界有广泛应用1. 数据校验Checksum网络传输中常用异或校验检测数据是否被篡改。例如发送方计算数据块的异或值作为校验码接收方重新计算并比对。2. 加密与安全一次性密码本One-time pad使用异或进行加密/解密。简单但理论上不可破解前提是密钥真随机且不重复使用。3. 内存优化在嵌入式系统或高频交易系统中常利用位运算节省内存。例如用一个 int 的 32 位表示 32 个布尔状态。4. 图形处理图像翻转、颜色混合等操作常使用位运算加速。5. 数据库去重虽然数据库不用异或去重但“成对抵消”的思想可用于日志分析、事务回滚等场景。✅结论这道题不仅是面试题更是位运算思维的启蒙课。十二、相关题目推荐LeetCode 拓展训练掌握本题后可挑战以下变种题号题目难度关键点137. 只出现一次的数字 II中等其余出现三次位计数模3260. 只出现一次的数字 III中等两个唯一数分组异或268. 丢失的数字简单0~n 缺一个异或或求和389. 找不同简单字符串中多一个字符异或字符477. 汉明距离总和中等所有数对的异或位数和位统计 建议先独立思考再参考题解形成自己的解题模板。十三、总结与延伸核心收获异或的三大性质是解决“成对抵消”类问题的利器。约束条件驱动算法选择线性时间 常量空间 → 位运算。从暴力到优化的思维路径是解决算法问题的标准流程。位运算不仅是技巧更是思维方式值得深入学习。延伸思考如果数组中有一个数出现一次其余出现k 次k 为奇数如何找答仍可用异或因 k 为奇数a ^ a ^ ... ^ a a如果 k 为偶数答异或结果为 0无法区分需其他方法如求和、位计数学习建议动手实现将本文所有思路都编码一遍对比性能。画图理解用二进制位图展示异或过程。阅读源码查看 JavaInteger.bitCount()等位操作方法。扩展阅读《算法导论》位运算章节、《Hacker’s Delight》结语“只出现一次的数字”看似简单却蕴含着算法设计的精髓在约束条件下寻找最优解。它教会我们不是所有问题都需要复杂的数据结构有时一个巧妙的位运算就能四两拨千斤。希望本文能帮助你在算法之路上更进一步。如果你觉得有收获欢迎点赞、收藏、转发也欢迎在评论区留下你的思考或疑问。Stay curious, keep coding!附完整可运行测试代码publicclassSingleNumber{publicstaticintsingleNumber(int[]nums){intresult0;for(intnum:nums){result^num;}returnresult;}publicstaticvoidmain(String[]args){System.out.println(singleNumber(newint[]{2,2,1}));// 1System.out.println(singleNumber(newint[]{4,1,2,1,2}));// 4System.out.println(singleNumber(newint[]{1}));// 1}}