LeetCode 268 Missing Number 缺失数字全解:排序、哈希集合、位运算 XOR 与数学求和四种解法对比

发布时间:2026/9/18 23:13:08

LeetCode 268 Missing Number 缺失数字全解:排序、哈希集合、位运算 XOR 与数学求和四种解法对比 LeetCode 268 Missing Number 缺失数字全解排序、哈希集合、位运算 XOR 与数学求和四种解法对比【免费下载链接】leetcodeLeetcode solutions项目地址: https://gitcode.com/GitHub_Trending/leetcode1/leetcode导读Missing Number缺失数字是 LeetCode 上经典的数组入门题给定一个包含n个互不相同数字的数组数字取自[0, n]区间其中恰好缺失一个数字要求找出它。本仓库以 articles/missing-number.md 为主干完整收录了排序、哈希集合、位运算 XOR 与数学求和四种解法并在 python/、cpp/、go/、rust/、javascript/ 等十余种语言目录下提供了对应实现如 cpp/0268-missing-number.cpp、python/0268-missing-number.py。读完本文你将掌握这道题的四种解题思路、时间复杂度对比以及常见的边界陷阱能够举一反三地迁移到其他查找缺失/重复元素类问题。前置知识在动手解决本题之前建议先熟悉以下三个基础概念它们是文中四种解法的底层支撑位运算 XOR异或XOR 解法利用a ^ a 0的性质让所有成对出现的数字互相抵消最终只剩下缺失的那个数字。数学求和公式数学解法利用0到n连续整数的求和公式用期望总和减去数组实际总和得到缺失值。哈希集合Hash Set哈希解法利用集合的常数时间查找能力快速判断[0, n]中哪个数字没有出现在数组里。仓库中的 hints/missing-number.md 给出了官方的进阶提示脉络从暴力O(n²)的逐个比对到用哈希集合优化为O(n)时间再到用位运算进一步把空间压缩到O(1)完整呈现了从朴素到最优的思维进化路径。问题定义与边界条件数组长度为n其中包含n个互不相同的数字全部取自区间[0, n]。由于区间内有n 1个整数而数组只有n个元素因此恰好缺失一个数字。关键边界条件有两个缺失数字可能是n本身。例如nums [0, 1]n 2缺失的是2也就是n。任何只遍历索引0到n - 1的解法都会漏掉这个答案。数组是无序的。输入并不保证排序因此排序解法必须显式先排序其他解法则完全不受顺序影响。仓库 cpp/0268-missing-number.cpp 的注释中用两个例子说明了这一设定nums [3, 0, 1]缺失2nums [0, 1]缺失2。解法一排序Sorting核心直觉如果数组是完整且有序的那么索引i位置上的值应当恰好等于i。一旦出现nums[i] ! i这个索引i就是缺失的数字。排序把乱序数组排好让这个对比变得直观是最适合初学者理解的做法。算法步骤将数组按升序排序。从索引0遍历到n - 1若nums[i] ! i说明i缺失直接返回i。若所有索引都与值匹配说明缺失的是n返回n。以nums [3, 0, 1]为例排序后为[0, 1, 3]i 0时nums[0] 0i 1时nums[1] 1i 2时nums[2] 3 ! 2返回2。多语言实现class Solution: def missingNumber(self, nums: List[int]) - int: n len(nums) nums.sort() for i in range(n): if nums[i] ! i: return i return nclass Solution { public: int missingNumber(vectorint nums) { int n nums.size(); sort(nums.begin(), nums.end()); for (int i 0; i n; i) { if (nums[i] ! i) { return i; } } return n; } };public class Solution { public int missingNumber(int[] nums) { int n nums.length; Arrays.sort(nums); for (int i 0; i n; i) { if (nums[i] ! i) { return i; } } return n; } }class Solution { /** * param {number[]} nums * return {number} */ missingNumber(nums) { let n nums.length; nums.sort((a, b) a - b); for (let i 0; i n; i) { if (nums[i] ! i) { return i; } } return n; } }func missingNumber(nums []int) int { n : len(nums) sort.Ints(nums) for i : 0; i n; i { if nums[i] ! i { return i } } return n }impl Solution { pub fn missing_number(nums: Veci32) - i32 { let n nums.len() as i32; let mut nums nums; nums.sort(); for i in 0..nums.len() { if nums[i] ! i as i32 { return i as i32; } } n } }仓库中 C、C#、Kotlin、Swift 等语言的排序实现同样遵循这一模式可分别参考 c/0268-missing-number.c、csharp/0268-missing-number.cs、kotlin/0268-missing-number.kt、swift/0268-missing-number.swift。复杂度分析时间复杂度$O(n \log n)$主要开销来自排序。空间复杂度$O(1)$ 或 $O(n)$取决于排序算法是否使用额外空间。解法二哈希集合Hash Set核心直觉核心问题是能否快速判断某个数字是否存在于数组中。把数组元素全部放入哈希集合后对任意数字的成员判断都能在常数时间内完成。随后只需在[0, n]范围内逐个检查第一个不在集合中的数字就是答案。这种做法用少量额外空间换来了非常清晰简单的逻辑。算法步骤将数组所有元素插入哈希集合。遍历0到n的所有数字若某个数字不在集合中返回它作为缺失数字。因为恰好只有一个数字缺失该过程必然找到答案。多语言实现class Solution: def missingNumber(self, nums: List[int]) - int: num_set set(nums) n len(nums) for i in range(n 1): if i not in num_set: return iclass Solution { public: int missingNumber(vectorint nums) { unordered_setint num_set(nums.begin(), nums.end()); int n nums.size(); for (int i 0; i n; i) { if (num_set.find(i) num_set.end()) { return i; } } return -1; } };func missingNumber(nums []int) int { numSet : make(map[int]struct{}) for _, num : range nums { numSet[num] struct{}{} } n : len(nums) for i : 0; i n; i { if _, exists : numSet[i]; !exists { return i } } return -1 }其余语言的实现大同小异Java 使用HashSetJavaScript 使用SetKotlin 使用nums.toSet()Swift 使用Set(nums)Rust 使用HashSeti32收集迭代器此处不再逐一展开。注意循环上界是n含因为n本身可能是缺失值。复杂度分析时间复杂度$O(n)$插入与查询均为常数时间。空间复杂度$O(n)$用于存储哈希集合。解法三位运算 XORBitwise XOR核心直觉XOR 拥有三个关键性质a ^ a 0数字与自己异或抵消a ^ 0 aXOR 满足交换律与结合律运算顺序无关紧要因此把0到n的全部数字与数组中的全部数字一起异或每个在两边都出现的数字都会成对抵消最终剩下的只有缺失的那个数字。该方案无需排序也无需额外数据结构即可在线性时间、常数空间内求解。仓库 cpp/0268-missing-number.cpp 顶部注释用nums [0, 1, 3, 4]推导了完整过程Missing 4^(0^0)^(1^1)^(2^3)^(3^4) (4^4)^(0^0)^(1^1)^(3^3)^2 0^0^0^0^2 2这正是a ^ a 0与交换结合律的直观体现。算法步骤令n为数组长度。初始化变量xorr n先纳入缺失候选值n。遍历i从0到n - 1xorr ^ ixorr ^ nums[i]循环结束后xorr即缺失数字返回它。多语言实现class Solution: def missingNumber(self, nums: List[int]) - int: n len(nums) xorr n for i in range(n): xorr ^ i ^ nums[i] return xorrclass Solution { public: int missingNumber(vectorint nums) { int n nums.size(); int xorr n; for (int i 0; i n; i) { xorr ^ i ^ nums[i]; } return xorr; } };impl Solution { pub fn missing_number(nums: Veci32) - i32 { let n nums.len() as i32; let mut xorr n; for i in 0..nums.len() { xorr ^ i as i32 ^ nums[i]; } xorr } }/** * https://leetcode.com/problems/missing-number/ * Time O(N) | Space O(1) * param {number[]} nums * return {number} */ var missingNumber function (nums, missingNumber nums.length) { for (let i 0; i nums.length; i) { const xor i ^ nums[i]; missingNumber ^ xor; } return missingNumber; };仓库中的 rust/0268-missing-number.rs 与 javascript/0268-missing-number.js 采用了完全相同的 XOR 策略其中 JavaScript 版本利用默认参数把n直接作为missingNumber的初始值写法更为紧凑。复杂度分析时间复杂度$O(n)$单次线性遍历。空间复杂度$O(1)$仅使用一个整型变量。解法四数学求和Math核心直觉数学观察非常简洁0到n的连续整数之和是已知的。用期望总和减去数组实际元素之和差值就是缺失的数字。为避免分别计算两个总和可能带来的溢出问题可以在单次循环中边加边减res初始为n每轮先加i再减nums[i]循环结束后res即为答案。这样既保持了逻辑干净又在部分语言中规避了溢出风险。算法步骤令n为数组长度。初始化变量res n。遍历i从0到n - 1res ires - nums[i]循环结束后res即缺失数字返回它。多语言实现class Solution: def missingNumber(self, nums: List[int]) - int: res len(nums) for i in range(len(nums)): res i - nums[i] return resfunc missingNumber(nums []int) int { res : len(nums) for i : 0; i len(nums); i { res i - nums[i] } return res }public class Solution { public int missingNumber(int[] nums) { int res nums.length; for (int i 0; i nums.length; i) { res i - nums[i]; } return res; } }class Solution { func missingNumber(_ nums: [Int]) - Int { var res nums.count for i in 0...nums.count-1 { res i - nums[i] } return res } }仓库中的 python/0268-missing-number.py 与 go/0268-missing-number.go 正是该单循环边加边减写法的实现。需要注意的是java/0268-missing-number.java 选择了另一种等价写法先计算total n * (n 1) / 2再减去数组和sum得到答案——这对应原文档中提到的先算完整期望和的版本在n极大时存在溢出风险需结合语言整数类型谨慎使用。复杂度分析时间复杂度$O(n)$。空间复杂度$O(1)$。常见陷阱Common Pitfalls陷阱一忘记n本身可能就是缺失值数组长度为n取值范围是[0, n]因此n本身也可能缺失。只检查索引0到n - 1的解法会在其他数字全部齐全时漏掉n无法返回正确答案。四种解法都通过循环结束后返回n或初始值设为n的方式覆盖了这一情况。陷阱二求和方案的整数溢出使用数学方法时若先单独计算完整期望和n * (n 1) / 2再相减当n很大时可能发生整数溢出。把加法和减法合并到同一个循环中res i - nums[i]可有效规避该问题这也是原文档推荐单循环写法的原因。若必须使用两段式写法如 java/0268-missing-number.java应确认语言整数类型能容纳n * (n 1)的上限。四种解法对比总结解法核心思想时间复杂度空间复杂度是否原地适用场景排序排好序后比较nums[i]与i$O(n \log n)$$O(1)$ 或 $O(n)$取决于排序算法初学者理解有序对比哈希集合集合常数时间成员查询$O(n)$$O(n)$否逻辑最清晰直观位运算 XOR成对抵消、仅剩缺失值$O(n)$$O(1)$是面试最优解兼顾时间与空间数学求和期望和减实际和$O(n)$$O(1)$是无位运算偏好的语言从仓库 hints/missing-number.md 的建议来看本题的目标是达到$O(n)$ 时间、$O(1)$ 空间即 XOR 与数学求和两种方案。它们不需要任何额外数据结构是面试与竞赛场景下的首选排序方案胜在直观哈希集合方案胜在思路通用都是理解进阶解法之前的重要铺垫。延伸阅读本题的思想可迁移到仓库内多道相关题目articles/find-all-numbers-disappeared-in-an-array.md[1, n]范围内可能出现多个缺失数字需借助下标标记技巧。articles/set-mismatch.md在一个缺失 一个重复的场景下XOR 与数学技巧依然适用。articles/first-missing-positive.md在任意数组中找第一个缺失正整数将值 ↔ 下标映射发挥到极致。articles/missing-element-in-sorted-array.md 与 articles/missing-number-in-arithmetic-progression.md在有序或等差背景下用二分查找定位缺失元素。阅读时建议对照各语言目录下的0268-missing-number.*文件如 c/0268-missing-number.c、typescript/0268-missing-number.ts、ruby/0268-missing-number.rb体会同一算法在不同语言生态中的惯用写法从而真正把思路内化为代码。【免费下载链接】leetcodeLeetcode solutions项目地址: https://gitcode.com/GitHub_Trending/leetcode1/leetcode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/18 23:13:08

企业为何要自建大模型?从数据安全到微调落地的全面解析

1. 先别急着站队:这个问题背后藏着一个真实困境我在很多技术社群和客户现场都遇到过同一个问题——公用大模型的能力已经强到“乱杀”了,一个API接进来,写文案、改代码、做翻译、抽信息样样都行,为什么还要花大价钱买GPU、组团队、…

2026/9/18 23:13:08

HHFT:异构层级特征的两级自注意力推荐模型

推荐系统做到一定阶段,多数团队都会撞上一堵墙:模型的离线指标怎么调都涨不动了,特征该加的也加了,样本量也够大,但AUC就是卡在某个数位上。这时候问题往往不在特征的数量,而在特征的组织方式。HHFT&#x…

2026/9/18 23:13:08

AI论文写作工具对比:千笔与锐智AI的核心技术与应用

1. 项目背景与核心价值作为一名经历过自考论文写作的过来人,我深知在工作和学习双重压力下完成学术论文的艰辛。2026年最新推出的这两款AI论文写作工具——千笔和锐智AI,正是为解决这个痛点而生。它们不仅仅是简单的文字生成器,而是整合了学术…

2026/9/19 0:08:11

Docker Desktop 设置转圈?WSL 后端与配置清理排查指南

点开 Docker Desktop 的齿轮图标,转圈转到你以为电脑死机——这事我遇到过不止一次。第一次碰上的时候我还在赶一个交付,容器跑得好好的,就是想改个镜像源,结果 Settings 页面那个加载动画转了整整八分钟没停。后来查日志、翻 iss…

2026/9/19 0:08:10

Docker Compose编排PostgreSQL、Chat2DB与监控栈

1. 单机场景下,为什么我依然离不开 docker-compose刚接触容器那会儿,我也觉得docker run敲一长串参数挺酷,直到某天要在本地拉起一套 PostgreSQL 加 Chat2DB 的数据开发环境,命令写完自己都记不住,第二天重启机器还得翻…

2026/9/19 0:08:10

UEditor在信创环境下导入Word文档的适配方案与踩坑记录

“百度UE”这个叫法我一听就知道,说的是百度开源的 UEditor——也就是那个在很多老后台管理系统里用了十多年的富文本编辑器。最近接了个国产化适配的活儿,客户给的验收清单里白纸黑字写着“支持在信创环境下导入 Word 文档”,第一反应就是拿…

2026/9/19 0:03:10

SYB创业计划书财务逻辑拆解:从销售收入预测到现金流量计划

简介:SYB创业计划书完整版.doc 是一份面向创业者、备赛学生及有开店打算人群的实用模板,以一家社区日用超市为案例,围绕企业概况、创业者个人情况、市场评估、市场营销计划、企业组织结构、固定资产、流动资金、销售收入预测、销售和成本计划…

2026/9/18 14:13:01

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/19 0:03:10

验证 OpenSpec 兼容性,Cursor 的 Token 从 TaoToken 出

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

2026/9/19 0:03:10

书桌角落的 Mac mini,OpenClaw 通过 TaoToken 跑任务。

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

2026/9/19 0:03:10

oh-my-hermes:打造跨工具的命令编排与插件化工作流

1. 项目概述与设计初衷1.1 它到底是什么先说结论:oh-my-hermes 是一个面向开发者日常终端操作的效率工具套件,核心定位是“把分散在各类命令行工具里的高频操作,统一收拢成一套插件化、可编排的工作流”。项目灵感来源很明显——oh-my-zsh 重…

2026/9/18 14:13:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/18 14:13:02

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/18 14:13:02

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码