找不到的那一个:Swift 解法带你轻松找出丢失的数字

在这里插入图片描述
在这里插入图片描述

摘要

这篇文章围绕 LeetCode 第 268 题“Missing Number”展开,讲的是如何从一个 [0, n] 的连续数字序列中,找出唯一缺失的那个数字。看上去像个数学题,但背后其实有不少技巧值得借鉴。我们将提供 Swift 解法,分析其背后的思路,并结合日常场景,聊聊为什么这种“对照差值”的方法在开发中非常常用。

描述

题目是这样说的:

你有一个长度为 n 的数组,里面是 [0, n] 之间的 n 个唯一整数。也就是说,总共应该有 n+1 个数字,但你手里只有 n 个,丢了一个。现在需要你把这个缺失的数字找出来。

举几个例子:

输入:nums = [3, 0, 1]
输出:2

输入:nums = [0, 1]
输出:2

输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8

这个题看起来挺“面试风”的,确实很多公司都会问这类数字序列类问题。它考的不是你写了多少行代码,而是你对“序列”这件事有没有底层理解。

题解答案

我们先贴一下 Swift 解法:

func missingNumber(_ nums: [Int]) -> Int {
    let n = nums.count
    let expectedSum = n * (n + 1) / 2
    let actualSum = nums.reduce(0, +)
    return expectedSum - actualSum
}

是不是看上去特别短?但其实这行代码里面的数学逻辑非常硬核,我们下面来拆解。

题解代码分析

用数学做“对照”

我们要找 [0, n] 中丢失的数字,假设这些数字全都在数组里,理论上它们的总和是 0 + 1 + 2 + ... + n,也就是:

n * (n + 1) / 2

这是一个非常经典的等差数列求和公式。如果我们把这个“应有的总和”减去我们实际拿到的 nums 数组中所有数字的总和,差值自然就是“丢的那一个”。

比如 nums = [3, 0, 1]

  • 应有总和是:3 * (3 + 1) / 2 = 6
  • 实际总和是:3 + 0 + 1 = 4
  • 差值是:6 - 4 = 2,也就是丢失的数字。

为什么用 reduce?

在 Swift 中,nums.reduce(0, +) 是一种非常常用的写法,等价于把数组里所有元素都加起来。比用 for 循环累加更清爽。

示例测试及结果

我们可以写一段简单的 Demo 来验证这段代码的正确性:

func testMissingNumber() {
    print(missingNumber([3, 0, 1]))              // 输出:2
    print(missingNumber([0, 1]))                 // 输出:2
    print(missingNumber([9,6,4,2,3,5,7,0,1]))     // 输出:8
    print(missingNumber([1]))                    // 输出:0
    print(missingNumber([0]))                    // 输出:1
}

testMissingNumber()

输出结果如下:

2
2
8
0
1

全部正确,说明逻辑没问题,代码也可以直接上手跑。

时间复杂度

遍历数组来计算总和的操作是一次性完成的,所以时间复杂度是:

O(n)

其中 n 是数组的长度。

空间复杂度

我们没有额外开数组或数据结构来做辅助存储,变量是常数个,所以空间复杂度是:

O(1)

这也是这道题的加分点——既快又省空间。

日常场景中的应用

别看这个题小,其实这种“差值求缺项”的方式,在日常开发里非常常见:

1. 报表对账

比如一个电商平台,每天会导出订单总数和财务总数,你用一对 SQL 算出来的数据总和跟系统报表一比,如果总和不一致,就能快速定位出“哪笔订单跑丢了”。

2. 枚举检测

在游戏开发中,有时候你给某个角色设计了编号为 0~50 的技能池,一旦某个编号技能丢失,系统可能会崩。写段检测代码来找出哪个技能配置没上线,用的就是这个思路。

3. 序列校验

在某些通信协议中,一段数据包传过来,每个包都有顺序编号,如果中间漏了一个编号,系统就要做容错或重发。快速检测丢失编号,也是这个逻辑。

总结

这道题背后其实考察的是“对数据整体结构的把握”。不是让你硬干暴力搜索,而是看你能不能抽象问题,用数学规律做“信息对照”。

如果你平时在做日志对账、ID序列校验、订单缺失检测等问题,不妨考虑一下类似的思路 —— 先想一想“我期望得到什么”,再和实际结果做差。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

网罗开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值